Skip to content

Commit

Permalink
Merge pull request #908 from square/zachklipp/worker-ktypes
Browse files Browse the repository at this point in the history
Use KType instead of KClass in TypedWorker.
  • Loading branch information
zach-klippenstein authored Jan 24, 2020
2 parents d5c3810 + 7391516 commit 99b7eae
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 6 deletions.
22 changes: 17 additions & 5 deletions kotlin/workflow-core/src/main/java/com/squareup/workflow/Worker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flow
import kotlin.experimental.ExperimentalTypeInference
import kotlin.reflect.KClass
import kotlin.reflect.KType
import kotlin.reflect.typeOf

/**
* Represents a unit of asynchronous work that can have zero, one, or multiple outputs.
Expand Down Expand Up @@ -179,6 +180,17 @@ interface Worker<out OutputT> {

companion object {

/**
* Use this value instead of calling `typeOf<Nothing>()` directly, which isn't allowed because
* [Nothing] isn't allowed as a reified type parameter.
*
* The KType of Nothing on the JVM is actually java.lang.Void if you do
* Nothing::class.createType(). However createType() lives in the reflection library, so we just
* reference Void directly so we don't have to add a dependency on kotlin-reflect.
*/
@UseExperimental(ExperimentalStdlibApi::class)
private val TYPE_OF_NOTHING = typeOf<Void>()

/**
* Shorthand for `flow { block() }.asWorker()`.
*
Expand Down Expand Up @@ -208,7 +220,7 @@ interface Worker<out OutputT> {
*/
fun createSideEffect(
block: suspend () -> Unit
): Worker<Nothing> = TypedWorker(Nothing::class, flow { block() })
): Worker<Nothing> = TypedWorker(TYPE_OF_NOTHING, flow { block() })

/**
* Returns a [Worker] that finishes immediately without emitting anything.
Expand Down Expand Up @@ -259,8 +271,9 @@ interface Worker<out OutputT> {
/**
* Returns a [Worker] that will, when performed, emit whatever this [Flow] receives.
*/
@UseExperimental(ExperimentalStdlibApi::class)
inline fun <reified OutputT> Flow<OutputT>.asWorker(): Worker<OutputT> =
TypedWorker(OutputT::class, this)
TypedWorker(typeOf<OutputT>(), this)

/**
* Returns a [Worker] that will await this [Deferred] and then emit it.
Expand Down Expand Up @@ -361,8 +374,7 @@ fun <T, R> Worker<T>.transform(
*/
@PublishedApi
internal class TypedWorker<OutputT>(
/** Can't be `KClass<OutputT>` because `OutputT` doesn't have upper bound `Any`. */
private val type: KClass<*>,
private val type: KType,
private val work: Flow<OutputT>
) : Worker<OutputT> {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,22 @@ class WorkerTest {
assertTrue(Worker1().doesSameWorkAs(Worker1()))
assertFalse(Worker1().doesSameWorkAs(Worker2()))
}

@Test fun `createSideEffect workers are equivalent`() {
val worker1 = Worker.createSideEffect {}
val worker2 = Worker.createSideEffect {}
assertTrue(worker1.doesSameWorkAs(worker2))
}

@Test fun `TypedWorkers are compared by higher types`() {
val worker1 = Worker.create<List<Int>> { }
val worker2 = Worker.create<List<String>> { }
assertFalse(worker1.doesSameWorkAs(worker2))
}

@Test fun `TypedWorkers are equivalent with higher types`() {
val worker1 = Worker.create<List<Int>> { }
val worker2 = Worker.create<List<Int>> { }
assertTrue(worker1.doesSameWorkAs(worker2))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
{"name":"TracingDiagnosticListenerTest$TestWorkflow (0)","cat":"rendering","ph":"B","ts":0,"pid":0,"tid":0,"args":{"workflowId":"0","props":"2","state":"changed state"}},
{"name":"TracingDiagnosticListenerTest$TestWorkflow (1)","cat":"rendering","ph":"B","ts":0,"pid":0,"tid":0,"args":{"workflowId":"1","props":"0","state":"initial"}},
{"name":"TracingDiagnosticListenerTest$TestWorkflow (1)","cat":"rendering","ph":"E","ts":0,"pid":0,"tid":0,"args":{"rendering":"initial"}},
{"name":"Worker: 2","cat":"workflow","ph":"b","ts":0,"pid":0,"tid":0,"id":"workflow","args":{"parent":"TracingDiagnosticListenerTest$TestWorkflow (0)","key":"","description":"TypedWorker(class kotlin.String)"}},
{"name":"Worker: 2","cat":"workflow","ph":"b","ts":0,"pid":0,"tid":0,"id":"workflow","args":{"parent":"TracingDiagnosticListenerTest$TestWorkflow (0)","key":"","description":"TypedWorker(kotlin.String)"}},
{"name":"TracingDiagnosticListenerTest$TestWorkflow (0)","cat":"rendering","ph":"E","ts":0,"pid":0,"tid":0,"args":{"rendering":"rendering"}},
{"name":"Render Pass","cat":"rendering","ph":"E","ts":0,"pid":0,"tid":0,"args":{"rendering":"rendering"}},
{"name":"used/free memory","ph":"C","ts":0,"pid":0,"tid":0,"args":{"usedMemory":1,"freeMemory":42}},
Expand Down

0 comments on commit 99b7eae

Please sign in to comment.