mirror of
https://github.com/DaanVandenBosch/phantasmal-world.git
synced 2025-04-07 08:48:28 +08:00
Renamed StaticCell to ImmutableCell and StaticListCell to ImmutableListCell.
This commit is contained in:
parent
b7fc6a260b
commit
5c605fafbc
@ -1,21 +1,27 @@
|
|||||||
package world.phantasmal.observable.cell
|
package world.phantasmal.observable.cell
|
||||||
|
|
||||||
private val TRUE_CELL: Cell<Boolean> = StaticCell(true)
|
private val TRUE_CELL: Cell<Boolean> = ImmutableCell(true)
|
||||||
private val FALSE_CELL: Cell<Boolean> = StaticCell(false)
|
private val FALSE_CELL: Cell<Boolean> = ImmutableCell(false)
|
||||||
private val NULL_CELL: Cell<Nothing?> = StaticCell(null)
|
private val NULL_CELL: Cell<Nothing?> = ImmutableCell(null)
|
||||||
private val ZERO_INT_CELL: Cell<Int> = StaticCell(0)
|
private val ZERO_INT_CELL: Cell<Int> = ImmutableCell(0)
|
||||||
private val EMPTY_STRING_CELL: Cell<String> = StaticCell("")
|
private val EMPTY_STRING_CELL: Cell<String> = ImmutableCell("")
|
||||||
|
|
||||||
fun <T> cell(value: T): Cell<T> = StaticCell(value)
|
/** Returns an immutable cell containing [value]. */
|
||||||
|
fun <T> cell(value: T): Cell<T> = ImmutableCell(value)
|
||||||
|
|
||||||
|
/** Returns a singleton immutable cell containing the value `true`. */
|
||||||
fun trueCell(): Cell<Boolean> = TRUE_CELL
|
fun trueCell(): Cell<Boolean> = TRUE_CELL
|
||||||
|
|
||||||
|
/** Returns a singleton immutable cell containing the value `false`. */
|
||||||
fun falseCell(): Cell<Boolean> = FALSE_CELL
|
fun falseCell(): Cell<Boolean> = FALSE_CELL
|
||||||
|
|
||||||
|
/** Returns a singleton immutable cell containing the value `null`. */
|
||||||
fun nullCell(): Cell<Nothing?> = NULL_CELL
|
fun nullCell(): Cell<Nothing?> = NULL_CELL
|
||||||
|
|
||||||
|
/** Returns a singleton immutable cell containing the integer value `0`. */
|
||||||
fun zeroIntCell(): Cell<Int> = ZERO_INT_CELL
|
fun zeroIntCell(): Cell<Int> = ZERO_INT_CELL
|
||||||
|
|
||||||
|
/** Returns a singleton immutable cell containing the empty string (""). */
|
||||||
fun emptyStringCell(): Cell<String> = EMPTY_STRING_CELL
|
fun emptyStringCell(): Cell<String> = EMPTY_STRING_CELL
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6,7 +6,7 @@ import world.phantasmal.observable.AbstractDependency
|
|||||||
import world.phantasmal.observable.ChangeEvent
|
import world.phantasmal.observable.ChangeEvent
|
||||||
import world.phantasmal.observable.Observer
|
import world.phantasmal.observable.Observer
|
||||||
|
|
||||||
class StaticCell<T>(override val value: T) : AbstractDependency(), Cell<T> {
|
class ImmutableCell<T>(override val value: T) : AbstractDependency(), Cell<T> {
|
||||||
override fun observe(callNow: Boolean, observer: Observer<T>): Disposable {
|
override fun observe(callNow: Boolean, observer: Observer<T>): Disposable {
|
||||||
if (callNow) {
|
if (callNow) {
|
||||||
observer(ChangeEvent(value))
|
observer(ChangeEvent(value))
|
@ -1,6 +1,5 @@
|
|||||||
package world.phantasmal.observable.cell.list
|
package world.phantasmal.observable.cell.list
|
||||||
|
|
||||||
import world.phantasmal.core.unsafe.unsafeAssertNotNull
|
|
||||||
import world.phantasmal.observable.ChangeEvent
|
import world.phantasmal.observable.ChangeEvent
|
||||||
import world.phantasmal.observable.Dependency
|
import world.phantasmal.observable.Dependency
|
||||||
import world.phantasmal.observable.Dependent
|
import world.phantasmal.observable.Dependent
|
||||||
|
@ -8,7 +8,7 @@ import world.phantasmal.observable.ChangeEvent
|
|||||||
import world.phantasmal.observable.Observer
|
import world.phantasmal.observable.Observer
|
||||||
import world.phantasmal.observable.cell.*
|
import world.phantasmal.observable.cell.*
|
||||||
|
|
||||||
class StaticListCell<E>(private val elements: List<E>) : AbstractDependency(), ListCell<E> {
|
class ImmutableListCell<E>(private val elements: List<E>) : AbstractDependency(), ListCell<E> {
|
||||||
private var firstOrNull: Cell<E?>? = null
|
private var firstOrNull: Cell<E?>? = null
|
||||||
|
|
||||||
override val size: Cell<Int> = cell(elements.size)
|
override val size: Cell<Int> = cell(elements.size)
|
||||||
@ -40,13 +40,13 @@ class StaticListCell<E>(private val elements: List<E>) : AbstractDependency(), L
|
|||||||
|
|
||||||
override fun firstOrNull(): Cell<E?> {
|
override fun firstOrNull(): Cell<E?> {
|
||||||
if (firstOrNull == null) {
|
if (firstOrNull == null) {
|
||||||
firstOrNull = StaticCell(elements.firstOrNull())
|
firstOrNull = ImmutableCell(elements.firstOrNull())
|
||||||
}
|
}
|
||||||
|
|
||||||
return unsafeAssertNotNull(firstOrNull)
|
return unsafeAssertNotNull(firstOrNull)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun emitDependencyChanged() {
|
override fun emitDependencyChanged() {
|
||||||
error("StaticListCell can't change.")
|
error("ImmutableListCell can't change.")
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,12 +2,15 @@ package world.phantasmal.observable.cell.list
|
|||||||
|
|
||||||
import world.phantasmal.observable.cell.Cell
|
import world.phantasmal.observable.cell.Cell
|
||||||
|
|
||||||
private val EMPTY_LIST_CELL = StaticListCell<Nothing>(emptyList())
|
private val EMPTY_LIST_CELL = ImmutableListCell<Nothing>(emptyList())
|
||||||
|
|
||||||
fun <E> listCell(vararg elements: E): ListCell<E> = StaticListCell(elements.toList())
|
/** Returns an immutable list cell containing [elements]. */
|
||||||
|
fun <E> listCell(vararg elements: E): ListCell<E> = ImmutableListCell(elements.toList())
|
||||||
|
|
||||||
|
/** Returns a singleton empty immutable cell. */
|
||||||
fun <E> emptyListCell(): ListCell<E> = EMPTY_LIST_CELL
|
fun <E> emptyListCell(): ListCell<E> = EMPTY_LIST_CELL
|
||||||
|
|
||||||
|
/** Returns a mutable list cell containing [elements]. */
|
||||||
fun <E> mutableListCell(
|
fun <E> mutableListCell(
|
||||||
vararg elements: E,
|
vararg elements: E,
|
||||||
extractDependencies: DependenciesExtractor<E>? = null,
|
extractDependencies: DependenciesExtractor<E>? = null,
|
||||||
|
@ -55,7 +55,7 @@ interface CellTests : ObservableTests {
|
|||||||
fun propagates_changes_to_flat_mapped_cell() = test {
|
fun propagates_changes_to_flat_mapped_cell() = test {
|
||||||
val p = createProvider()
|
val p = createProvider()
|
||||||
|
|
||||||
val mapped = p.observable.flatMap { StaticCell(it.hashCode()) }
|
val mapped = p.observable.flatMap { ImmutableCell(it.hashCode()) }
|
||||||
val initialValue = mapped.value
|
val initialValue = mapped.value
|
||||||
|
|
||||||
var observedValue: Int? = null
|
var observedValue: Int? = null
|
||||||
|
@ -6,7 +6,7 @@ package world.phantasmal.observable.cell
|
|||||||
class FlatteningDependentCellDirectDependencyEmitsTests : RegularCellTests {
|
class FlatteningDependentCellDirectDependencyEmitsTests : RegularCellTests {
|
||||||
override fun createProvider() = object : CellTests.Provider {
|
override fun createProvider() = object : CellTests.Provider {
|
||||||
// The transitive dependency can't change.
|
// The transitive dependency can't change.
|
||||||
val transitiveDependency = StaticCell(5)
|
val transitiveDependency = ImmutableCell(5)
|
||||||
|
|
||||||
// The direct dependency of the cell under test can change.
|
// The direct dependency of the cell under test can change.
|
||||||
val directDependency = SimpleCell(transitiveDependency)
|
val directDependency = SimpleCell(transitiveDependency)
|
||||||
@ -17,12 +17,12 @@ class FlatteningDependentCellDirectDependencyEmitsTests : RegularCellTests {
|
|||||||
override fun emit() {
|
override fun emit() {
|
||||||
// Update the direct dependency.
|
// Update the direct dependency.
|
||||||
val oldTransitiveDependency = directDependency.value
|
val oldTransitiveDependency = directDependency.value
|
||||||
directDependency.value = StaticCell(oldTransitiveDependency.value + 5)
|
directDependency.value = ImmutableCell(oldTransitiveDependency.value + 5)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T> createWithValue(value: T): FlatteningDependentCell<T> {
|
override fun <T> createWithValue(value: T): FlatteningDependentCell<T> {
|
||||||
val v = StaticCell(StaticCell(value))
|
val v = ImmutableCell(ImmutableCell(value))
|
||||||
return FlatteningDependentCell(v) { v.value }
|
return FlatteningDependentCell(v) { v.value }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ class FlatteningDependentCellTransitiveDependencyEmitsTests :
|
|||||||
override fun createProvider() = Provider()
|
override fun createProvider() = Provider()
|
||||||
|
|
||||||
override fun <T> createWithValue(value: T): FlatteningDependentCell<T> {
|
override fun <T> createWithValue(value: T): FlatteningDependentCell<T> {
|
||||||
val dependency = StaticCell(StaticCell(value))
|
val dependency = ImmutableCell(ImmutableCell(value))
|
||||||
return FlatteningDependentCell(dependency) { dependency.value }
|
return FlatteningDependentCell(dependency) { dependency.value }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ class FlatteningDependentCellTransitiveDependencyEmitsTests :
|
|||||||
private val transitiveDependency = SimpleCell(5)
|
private val transitiveDependency = SimpleCell(5)
|
||||||
|
|
||||||
// The direct dependency of the cell under test can't change.
|
// The direct dependency of the cell under test can't change.
|
||||||
private val directDependency = StaticCell(transitiveDependency)
|
private val directDependency = ImmutableCell(transitiveDependency)
|
||||||
|
|
||||||
override val observable =
|
override val observable =
|
||||||
FlatteningDependentCell(directDependency) { directDependency.value }
|
FlatteningDependentCell(directDependency) { directDependency.value }
|
||||||
@ -30,6 +30,6 @@ class FlatteningDependentCellTransitiveDependencyEmitsTests :
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun createWithDependencies(vararg dependencies: Cell<Int>): Cell<Any> =
|
override fun createWithDependencies(vararg dependencies: Cell<Int>): Cell<Any> =
|
||||||
FlatteningDependentCell(*dependencies) { StaticCell(dependencies.sumOf { it.value }) }
|
FlatteningDependentCell(*dependencies) { ImmutableCell(dependencies.sumOf { it.value }) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
package world.phantasmal.observable.cell
|
||||||
|
|
||||||
|
import world.phantasmal.core.disposable.TrackedDisposable
|
||||||
|
import world.phantasmal.observable.test.ObservableTestSuite
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class ImmutableCellTests : ObservableTestSuite {
|
||||||
|
@Test
|
||||||
|
fun observing_it_should_never_create_leaks() = test {
|
||||||
|
val cell = ImmutableCell("test value")
|
||||||
|
|
||||||
|
TrackedDisposable.checkNoLeaks {
|
||||||
|
// We never call dispose on the returned disposables.
|
||||||
|
cell.observe {}
|
||||||
|
cell.observe(callNow = false) {}
|
||||||
|
cell.observe(callNow = true) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun observe_respects_callNow() = test {
|
||||||
|
val cell = ImmutableCell("test value")
|
||||||
|
var calls = 0
|
||||||
|
|
||||||
|
cell.observe(callNow = false) { calls++ }
|
||||||
|
cell.observe(callNow = true) { calls++ }
|
||||||
|
|
||||||
|
assertEquals(1, calls)
|
||||||
|
}
|
||||||
|
}
|
@ -1,28 +0,0 @@
|
|||||||
package world.phantasmal.observable.cell
|
|
||||||
|
|
||||||
import world.phantasmal.observable.test.ObservableTestSuite
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
class StaticCellTests : ObservableTestSuite {
|
|
||||||
@Test
|
|
||||||
fun observing_StaticCell_should_never_create_leaks() = test {
|
|
||||||
val static = StaticCell("test value")
|
|
||||||
|
|
||||||
// We never call dispose on the returned disposables.
|
|
||||||
static.observe {}
|
|
||||||
static.observe(callNow = false) {}
|
|
||||||
static.observe(callNow = true) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun observe_respects_callNow() = test {
|
|
||||||
val static = StaticCell("test value")
|
|
||||||
var calls = 0
|
|
||||||
|
|
||||||
static.observe(callNow = false) { calls++ }
|
|
||||||
static.observe(callNow = true) { calls++ }
|
|
||||||
|
|
||||||
assertEquals(1, calls)
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,7 +8,7 @@ import world.phantasmal.observable.cell.SimpleCell
|
|||||||
class FlatteningDependentListCellDirectDependencyEmitsTests : ListCellTests {
|
class FlatteningDependentListCellDirectDependencyEmitsTests : ListCellTests {
|
||||||
override fun createListProvider(empty: Boolean) = object : ListCellTests.Provider {
|
override fun createListProvider(empty: Boolean) = object : ListCellTests.Provider {
|
||||||
// The transitive dependency can't change.
|
// The transitive dependency can't change.
|
||||||
private val transitiveDependency = StaticListCell(if (empty) emptyList() else listOf(7))
|
private val transitiveDependency = ImmutableListCell(if (empty) emptyList() else listOf(7))
|
||||||
|
|
||||||
// The direct dependency of the list under test can change.
|
// The direct dependency of the list under test can change.
|
||||||
private val directDependency = SimpleCell<ListCell<Int>>(transitiveDependency)
|
private val directDependency = SimpleCell<ListCell<Int>>(transitiveDependency)
|
||||||
@ -19,7 +19,7 @@ class FlatteningDependentListCellDirectDependencyEmitsTests : ListCellTests {
|
|||||||
override fun addElement() {
|
override fun addElement() {
|
||||||
// Update the direct dependency.
|
// Update the direct dependency.
|
||||||
val oldTransitiveDependency: ListCell<Int> = directDependency.value
|
val oldTransitiveDependency: ListCell<Int> = directDependency.value
|
||||||
directDependency.value = StaticListCell(oldTransitiveDependency.value + 4)
|
directDependency.value = ImmutableListCell(oldTransitiveDependency.value + 4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ package world.phantasmal.observable.cell.list
|
|||||||
|
|
||||||
import world.phantasmal.observable.cell.Cell
|
import world.phantasmal.observable.cell.Cell
|
||||||
import world.phantasmal.observable.cell.CellWithDependenciesTests
|
import world.phantasmal.observable.cell.CellWithDependenciesTests
|
||||||
import world.phantasmal.observable.cell.StaticCell
|
import world.phantasmal.observable.cell.ImmutableCell
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In these tests the dependency of the [FlatteningDependentListCell]'s direct dependency changes.
|
* In these tests the dependency of the [FlatteningDependentListCell]'s direct dependency changes.
|
||||||
@ -21,7 +21,7 @@ class FlatteningDependentListCellTransitiveDependencyEmitsTests :
|
|||||||
SimpleListCell(if (empty) mutableListOf() else mutableListOf(7))
|
SimpleListCell(if (empty) mutableListOf() else mutableListOf(7))
|
||||||
|
|
||||||
// The direct dependency of the list under test can't change.
|
// The direct dependency of the list under test can't change.
|
||||||
private val directDependency = StaticCell<ListCell<Int>>(transitiveDependency)
|
private val directDependency = ImmutableCell<ListCell<Int>>(transitiveDependency)
|
||||||
|
|
||||||
override val observable =
|
override val observable =
|
||||||
FlatteningDependentListCell(directDependency) { directDependency.value }
|
FlatteningDependentListCell(directDependency) { directDependency.value }
|
||||||
@ -33,7 +33,7 @@ class FlatteningDependentListCellTransitiveDependencyEmitsTests :
|
|||||||
|
|
||||||
override fun createWithDependencies(vararg dependencies: Cell<Int>): Cell<Any> =
|
override fun createWithDependencies(vararg dependencies: Cell<Int>): Cell<Any> =
|
||||||
FlatteningDependentListCell(*dependencies) {
|
FlatteningDependentListCell(*dependencies) {
|
||||||
StaticListCell(dependencies.map { it.value })
|
ImmutableListCell(dependencies.map { it.value })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
package world.phantasmal.observable.cell.list
|
||||||
|
|
||||||
|
import world.phantasmal.core.disposable.TrackedDisposable
|
||||||
|
import world.phantasmal.observable.test.ObservableTestSuite
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class ImmutableListCellTests : ObservableTestSuite {
|
||||||
|
@Test
|
||||||
|
fun observing_it_should_never_create_leaks() = test {
|
||||||
|
val listCell = ImmutableListCell(listOf(1, 2, 3))
|
||||||
|
|
||||||
|
TrackedDisposable.checkNoLeaks {
|
||||||
|
// We never call dispose on the returned disposables.
|
||||||
|
listCell.observe {}
|
||||||
|
listCell.observe(callNow = false) {}
|
||||||
|
listCell.observe(callNow = true) {}
|
||||||
|
listCell.observeList(callNow = false) {}
|
||||||
|
listCell.observeList(callNow = true) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun observe_respects_callNow() = test {
|
||||||
|
val listCell = ImmutableListCell(listOf(1, 2, 3))
|
||||||
|
var calls = 0
|
||||||
|
|
||||||
|
listCell.observe(callNow = false) { calls++ }
|
||||||
|
listCell.observe(callNow = true) { calls++ }
|
||||||
|
|
||||||
|
assertEquals(1, calls)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun observeList_respects_callNow() = test {
|
||||||
|
val listCell = ImmutableListCell(listOf(1, 2, 3))
|
||||||
|
var calls = 0
|
||||||
|
|
||||||
|
listCell.observeList(callNow = false) { calls++ }
|
||||||
|
listCell.observeList(callNow = true) { calls++ }
|
||||||
|
|
||||||
|
assertEquals(1, calls)
|
||||||
|
}
|
||||||
|
}
|
@ -1,41 +0,0 @@
|
|||||||
package world.phantasmal.observable.cell.list
|
|
||||||
|
|
||||||
import world.phantasmal.observable.test.ObservableTestSuite
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
class StaticListCellTests : ObservableTestSuite {
|
|
||||||
@Test
|
|
||||||
fun observing_StaticListCell_should_never_create_leaks() = test {
|
|
||||||
val static = StaticListCell(listOf(1, 2, 3))
|
|
||||||
|
|
||||||
// We never call dispose on the returned disposables.
|
|
||||||
static.observe {}
|
|
||||||
static.observe(callNow = false) {}
|
|
||||||
static.observe(callNow = true) {}
|
|
||||||
static.observeList(callNow = false) {}
|
|
||||||
static.observeList(callNow = true) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun observe_respects_callNow() = test {
|
|
||||||
val static = StaticListCell(listOf(1, 2, 3))
|
|
||||||
var calls = 0
|
|
||||||
|
|
||||||
static.observe(callNow = false) { calls++ }
|
|
||||||
static.observe(callNow = true) { calls++ }
|
|
||||||
|
|
||||||
assertEquals(1, calls)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun observeList_respects_callNow() = test {
|
|
||||||
val static = StaticListCell(listOf(1, 2, 3))
|
|
||||||
var calls = 0
|
|
||||||
|
|
||||||
static.observeList(callNow = false) { calls++ }
|
|
||||||
static.observeList(callNow = true) { calls++ }
|
|
||||||
|
|
||||||
assertEquals(1, calls)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user