From 85b34497ef9f0f307e18c8228f65fbde444c2442 Mon Sep 17 00:00:00 2001 From: Ray Ryan Date: Sat, 23 Apr 2022 14:41:45 -0700 Subject: [PATCH] Introduces ViewEnvironmentKey.combine, makes ViewRegistry use it. `ViewEnvironmentKey.combine` is called from `ViewEnvironment.plus` when both operands have keys of the same type. `ViewRegistry.Companion` is already a `ViewEnvironmentKey`, and now it implements `combine`, calling `ViewRegistry.merge`. This changes `ViewEnvironment.plus` to merge the values of `ViewRegistry` entries instead of replacing the registry on the left with the one on the right, which is the only thing we've ever actually wanted to do. This allows us to eliminate `ViewEnvironment.merge`. We have never seen a use case for completely stomping the `ViewRegistry` on the left, but have done it by accident a lot. If the need really does arise, we can add a `ViewEnvironment.minus` operator. Also eliminates the `ViewEnvironmentKey()` factory function, which was just silly. --- gradle.properties | 2 +- workflow-ui/core-android/api/core-android.api | 7 ++- .../squareup/workflow1/ui/ScreenViewHolder.kt | 4 +- .../ui/container/BackStackContainer.kt | 3 +- .../ui/container/BodyAndModalsContainer.kt | 3 +- .../EnvironmentScreenLegacyViewFactory.kt | 3 +- .../container/EnvironmentScreenViewFactory.kt | 5 +- workflow-ui/core-common/api/core-common.api | 11 ++-- .../squareup/workflow1/ui/ViewEnvironment.kt | 49 +++++++++++------ .../com/squareup/workflow1/ui/ViewRegistry.kt | 45 ++++----------- .../ui/container/EnvironmentScreen.kt | 6 +- .../workflow1/ui/ViewEnvironmentTest.kt | 18 ++++++ .../squareup/workflow1/ui/ViewRegistryTest.kt | 55 ++++++------------- 13 files changed, 100 insertions(+), 111 deletions(-) diff --git a/gradle.properties b/gradle.properties index 648ab2dfe4..2ccf1653b8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ android.useAndroidX=true systemProp.org.gradle.internal.publish.checksums.insecure=true GROUP=com.squareup.workflow1 -VERSION_NAME=1.8.0-uiUpdate03-SNAPSHOT +VERSION_NAME=1.8.0-uiUpdate04-SNAPSHOT POM_DESCRIPTION=Square Workflow diff --git a/workflow-ui/core-android/api/core-android.api b/workflow-ui/core-android/api/core-android.api index fff19b9e8f..977407be60 100644 --- a/workflow-ui/core-android/api/core-android.api +++ b/workflow-ui/core-android/api/core-android.api @@ -199,7 +199,12 @@ public abstract interface class com/squareup/workflow1/ui/ScreenViewHolder { } public final class com/squareup/workflow1/ui/ScreenViewHolder$Companion { - public final fun getShowing ()Lcom/squareup/workflow1/ui/ViewEnvironmentKey; +} + +public final class com/squareup/workflow1/ui/ScreenViewHolder$Companion$Showing : com/squareup/workflow1/ui/ViewEnvironmentKey { + public static final field INSTANCE Lcom/squareup/workflow1/ui/ScreenViewHolder$Companion$Showing; + public fun getDefault ()Lcom/squareup/workflow1/ui/Screen; + public synthetic fun getDefault ()Ljava/lang/Object; } public final class com/squareup/workflow1/ui/ScreenViewHolder$Companion$ShowingNothing : com/squareup/workflow1/ui/Screen { diff --git a/workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/ScreenViewHolder.kt b/workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/ScreenViewHolder.kt index b016f869f8..45136e3ea4 100644 --- a/workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/ScreenViewHolder.kt +++ b/workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/ScreenViewHolder.kt @@ -44,7 +44,9 @@ public interface ScreenViewHolder { * Provides access to the [Screen] instance most recently shown in a [ScreenViewHolder]'s * [view] via [show]. Call [showing] for more convenient access. */ - public val Showing: ViewEnvironmentKey = ViewEnvironmentKey { ShowingNothing } + public object Showing : ViewEnvironmentKey(Screen::class) { + override val default: Screen = ShowingNothing + } } } diff --git a/workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/BackStackContainer.kt b/workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/BackStackContainer.kt index 0e179d5fbc..d3ba0f948c 100644 --- a/workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/BackStackContainer.kt +++ b/workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/BackStackContainer.kt @@ -20,6 +20,7 @@ import com.squareup.workflow1.ui.Compatible.Companion.keyFor import com.squareup.workflow1.ui.NamedScreen import com.squareup.workflow1.ui.R import com.squareup.workflow1.ui.ScreenViewHolder +import com.squareup.workflow1.ui.ScreenViewHolder.Companion.Showing import com.squareup.workflow1.ui.ViewEnvironment import com.squareup.workflow1.ui.WorkflowUiExperimentalApi import com.squareup.workflow1.ui.androidx.WorkflowAndroidXSupport.stateRegistryOwnerFromViewTreeOrContext @@ -65,7 +66,7 @@ public open class BackStackContainer @JvmOverloads constructor( newRendering: BackStackScreen<*>, newViewEnvironment: ViewEnvironment ) { - savedStateParentKey = keyFor(newViewEnvironment[ScreenViewHolder.Showing]) + savedStateParentKey = keyFor(newViewEnvironment[Showing]) val config = if (newRendering.backStack.isEmpty()) First else Other val environment = newViewEnvironment + config diff --git a/workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/BodyAndModalsContainer.kt b/workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/BodyAndModalsContainer.kt index 486049a36d..9fdc00c010 100644 --- a/workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/BodyAndModalsContainer.kt +++ b/workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/BodyAndModalsContainer.kt @@ -17,6 +17,7 @@ import com.squareup.workflow1.ui.Compatible.Companion.keyFor import com.squareup.workflow1.ui.R import com.squareup.workflow1.ui.ScreenViewFactory import com.squareup.workflow1.ui.ScreenViewHolder +import com.squareup.workflow1.ui.ScreenViewHolder.Companion.Showing import com.squareup.workflow1.ui.ViewEnvironment import com.squareup.workflow1.ui.WorkflowUiExperimentalApi import com.squareup.workflow1.ui.WorkflowViewStub @@ -82,7 +83,7 @@ internal class BodyAndModalsContainer @JvmOverloads constructor( newScreen: BodyAndModalsScreen<*, *>, viewEnvironment: ViewEnvironment ) { - savedStateParentKey = keyFor(viewEnvironment[ScreenViewHolder.Showing]) + savedStateParentKey = keyFor(viewEnvironment[Showing]) val showingModals = newScreen.modals.isNotEmpty() diff --git a/workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/EnvironmentScreenLegacyViewFactory.kt b/workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/EnvironmentScreenLegacyViewFactory.kt index 1cf55202a7..e568c047be 100644 --- a/workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/EnvironmentScreenLegacyViewFactory.kt +++ b/workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/EnvironmentScreenLegacyViewFactory.kt @@ -5,7 +5,6 @@ package com.squareup.workflow1.ui.container import com.squareup.workflow1.ui.DecorativeViewFactory import com.squareup.workflow1.ui.ViewFactory import com.squareup.workflow1.ui.WorkflowUiExperimentalApi -import com.squareup.workflow1.ui.merge @Suppress("DEPRECATION") @WorkflowUiExperimentalApi @@ -13,6 +12,6 @@ internal object EnvironmentScreenLegacyViewFactory : ViewFactory - Pair(environmentScreen.wrapped, environmentScreen.environment merge inheritedEnvironment) + Pair(environmentScreen.wrapped, environmentScreen.environment + inheritedEnvironment) } ) diff --git a/workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/EnvironmentScreenViewFactory.kt b/workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/EnvironmentScreenViewFactory.kt index 46612e67ae..b139451644 100644 --- a/workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/EnvironmentScreenViewFactory.kt +++ b/workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/EnvironmentScreenViewFactory.kt @@ -4,7 +4,6 @@ import com.squareup.workflow1.ui.Screen import com.squareup.workflow1.ui.ScreenViewFactory import com.squareup.workflow1.ui.ScreenViewFactory.Companion.fromCode import com.squareup.workflow1.ui.WorkflowUiExperimentalApi -import com.squareup.workflow1.ui.merge import com.squareup.workflow1.ui.toUnwrappingViewFactory import com.squareup.workflow1.ui.toViewFactory @@ -12,13 +11,13 @@ import com.squareup.workflow1.ui.toViewFactory internal fun EnvironmentScreenViewFactory(): ScreenViewFactory> { return fromCode { initialEnvScreen, initialEnvironment, context, container -> - val mergedInitialEnvironment = initialEnvironment merge initialEnvScreen.environment + val mergedInitialEnvironment = initialEnvironment + initialEnvScreen.environment initialEnvScreen.wrapped.toViewFactory(mergedInitialEnvironment) .toUnwrappingViewFactory, WrappedT>( unwrap = { it.wrapped }, showWrapperScreen = { _, envScreen, environment, showUnwrapped -> - showUnwrapped(envScreen.wrapped, environment merge envScreen.environment) + showUnwrapped(envScreen.wrapped, environment + envScreen.environment) } ) .buildView(initialEnvScreen, mergedInitialEnvironment, context, container) diff --git a/workflow-ui/core-common/api/core-common.api b/workflow-ui/core-common/api/core-common.api index f18bf4368d..fc5a31fe09 100644 --- a/workflow-ui/core-common/api/core-common.api +++ b/workflow-ui/core-common/api/core-common.api @@ -102,14 +102,11 @@ public final class com/squareup/workflow1/ui/ViewEnvironment$Companion { public abstract class com/squareup/workflow1/ui/ViewEnvironmentKey { public fun (Lkotlin/reflect/KClass;)V + public fun combine (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public final fun equals (Ljava/lang/Object;)Z public abstract fun getDefault ()Ljava/lang/Object; public final fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class com/squareup/workflow1/ui/ViewEnvironmentKt { - public static final synthetic fun ViewEnvironmentKey (Lkotlin/jvm/functions/Function0;)Lcom/squareup/workflow1/ui/ViewEnvironmentKey; + public final fun toString ()Ljava/lang/String; } public abstract interface class com/squareup/workflow1/ui/ViewRegistry { @@ -119,6 +116,8 @@ public abstract interface class com/squareup/workflow1/ui/ViewRegistry { } public final class com/squareup/workflow1/ui/ViewRegistry$Companion : com/squareup/workflow1/ui/ViewEnvironmentKey { + public fun combine (Lcom/squareup/workflow1/ui/ViewRegistry;Lcom/squareup/workflow1/ui/ViewRegistry;)Lcom/squareup/workflow1/ui/ViewRegistry; + public synthetic fun combine (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun getDefault ()Lcom/squareup/workflow1/ui/ViewRegistry; public synthetic fun getDefault ()Ljava/lang/Object; } @@ -131,8 +130,6 @@ public final class com/squareup/workflow1/ui/ViewRegistryKt { public static final fun ViewRegistry ()Lcom/squareup/workflow1/ui/ViewRegistry; public static final fun ViewRegistry ([Lcom/squareup/workflow1/ui/ViewRegistry$Entry;)Lcom/squareup/workflow1/ui/ViewRegistry; public static final synthetic fun get (Lcom/squareup/workflow1/ui/ViewRegistry;Lkotlin/reflect/KClass;)Lcom/squareup/workflow1/ui/ViewRegistry$Entry; - public static final fun merge (Lcom/squareup/workflow1/ui/ViewEnvironment;Lcom/squareup/workflow1/ui/ViewEnvironment;)Lcom/squareup/workflow1/ui/ViewEnvironment; - public static final fun merge (Lcom/squareup/workflow1/ui/ViewEnvironment;Lcom/squareup/workflow1/ui/ViewRegistry;)Lcom/squareup/workflow1/ui/ViewEnvironment; public static final fun merge (Lcom/squareup/workflow1/ui/ViewRegistry;Lcom/squareup/workflow1/ui/ViewRegistry;)Lcom/squareup/workflow1/ui/ViewRegistry; public static final fun plus (Lcom/squareup/workflow1/ui/ViewEnvironment;Lcom/squareup/workflow1/ui/ViewRegistry;)Lcom/squareup/workflow1/ui/ViewEnvironment; public static final fun plus (Lcom/squareup/workflow1/ui/ViewRegistry;Lcom/squareup/workflow1/ui/ViewRegistry$Entry;)Lcom/squareup/workflow1/ui/ViewRegistry; diff --git a/workflow-ui/core-common/src/main/java/com/squareup/workflow1/ui/ViewEnvironment.kt b/workflow-ui/core-common/src/main/java/com/squareup/workflow1/ui/ViewEnvironment.kt index 3a51ff3105..bb7d084928 100644 --- a/workflow-ui/core-common/src/main/java/com/squareup/workflow1/ui/ViewEnvironment.kt +++ b/workflow-ui/core-common/src/main/java/com/squareup/workflow1/ui/ViewEnvironment.kt @@ -19,19 +19,30 @@ public class ViewEnvironment constructor( public val map: Map, Any> = emptyMap() ) { - @Suppress("UNCHECKED_CAST") - public operator fun get(key: ViewEnvironmentKey): T = map[key] as? T ?: key.default + public operator fun get(key: ViewEnvironmentKey): T = getOrNull(key) ?: key.default - @Suppress("DEPRECATION") - public operator fun plus(pair: Pair, T>): ViewEnvironment = - ViewEnvironment(map + pair) + public operator fun plus(pair: Pair, T>): ViewEnvironment { + val (newKey, newValue) = pair + val newPair = getOrNull(newKey) + ?.let { oldValue -> newKey to newKey.combine(oldValue, newValue) } + ?: pair + @Suppress("DEPRECATION") + return ViewEnvironment(map + newPair) + } @Suppress("DEPRECATION") public operator fun plus(other: ViewEnvironment): ViewEnvironment { if (this == other) return this if (other.map.isEmpty()) return this - if (this.map.isEmpty()) return other - return ViewEnvironment(map + other.map) + if (map.isEmpty()) return other + val newMap = map.toMutableMap() + other.map.entries.forEach { (key, value) -> + @Suppress("UNCHECKED_CAST") + newMap[key] = getOrNull(key as ViewEnvironmentKey) + ?.let { oldValue -> key.combine(oldValue, value) } + ?: value + } + return ViewEnvironment(newMap) } override fun toString(): String = "ViewEnvironment($map)" @@ -41,6 +52,9 @@ constructor( override fun hashCode(): Int = map.hashCode() + @Suppress("UNCHECKED_CAST") + private fun getOrNull(key: ViewEnvironmentKey): T? = map[key] as? T + public companion object { @Suppress("DEPRECATION") public val EMPTY: ViewEnvironment = ViewEnvironment() @@ -57,6 +71,15 @@ public abstract class ViewEnvironmentKey( ) { public abstract val default: T + /** + * Applied from [ViewEnvironment.plus] when the receiving environment already contains + * a value for this key. The default implementation replaces [left] with [right]. + */ + public open fun combine( + left: T, + right: T + ): T = right + final override fun equals(other: Any?): Boolean = when { this === other -> true other != null && this::class != other::class -> false @@ -65,17 +88,7 @@ public abstract class ViewEnvironmentKey( final override fun hashCode(): Int = type.hashCode() - override fun toString(): String { + final override fun toString(): String { return "${this::class.simpleName}(${type.simpleName})" } } - -@WorkflowUiExperimentalApi -public inline fun ViewEnvironmentKey( - crossinline produceDefault: () -> T, -): ViewEnvironmentKey { - return object : ViewEnvironmentKey(T::class) { - override val default: T - get() = produceDefault() - } -} diff --git a/workflow-ui/core-common/src/main/java/com/squareup/workflow1/ui/ViewRegistry.kt b/workflow-ui/core-common/src/main/java/com/squareup/workflow1/ui/ViewRegistry.kt index 987ce84f40..d90d37ab0a 100644 --- a/workflow-ui/core-common/src/main/java/com/squareup/workflow1/ui/ViewRegistry.kt +++ b/workflow-ui/core-common/src/main/java/com/squareup/workflow1/ui/ViewRegistry.kt @@ -83,6 +83,10 @@ public interface ViewRegistry { public companion object : ViewEnvironmentKey(ViewRegistry::class) { override val default: ViewRegistry get() = ViewRegistry() + override fun combine( + left: ViewRegistry, + right: ViewRegistry + ): ViewRegistry = left.merge(right) } } @@ -103,13 +107,17 @@ public fun ViewRegistry(vararg bindings: Entry<*>): ViewRegistry = public fun ViewRegistry(): ViewRegistry = TypedViewRegistry() /** - * @throws IllegalArgumentException if the receiver already has a matching [entry]. + * Transforms the receiver to add [entry], throwing [IllegalArgumentException] if the receiver + * already has a matching [entry]. Use [merge] to replace an existing entry with a new one. */ @WorkflowUiExperimentalApi public operator fun ViewRegistry.plus(entry: Entry<*>): ViewRegistry = this + ViewRegistry(entry) -/** @throws IllegalArgumentException if other has redundant entries. */ +/** + * Transforms the receiver to add all entries from [other], throwing [IllegalArgumentException] + * if the receiver already has any matching [entry]. Use [merge] to replace existing entries. + */ @WorkflowUiExperimentalApi public operator fun ViewRegistry.plus(other: ViewRegistry): ViewRegistry { if (other.keys.isEmpty()) return this @@ -117,10 +125,6 @@ public operator fun ViewRegistry.plus(other: ViewRegistry): ViewRegistry { return CompositeViewRegistry(this, other) } -/** - * Replaces the existing [ViewRegistry] of the receiver with [registry]. Use - * [ViewEnvironment.merge] to combine them instead. - */ @WorkflowUiExperimentalApi public operator fun ViewEnvironment.plus(registry: ViewRegistry): ViewEnvironment { if (this[ViewRegistry] === registry) return this @@ -144,32 +148,3 @@ public infix fun ViewRegistry.merge(other: ViewRegistry): ViewRegistry { .toTypedArray() .let { ViewRegistry(*it) } } - -/** - * Merges the [ViewRegistry] of the receiver with [registry]. If there are conflicting entries, - * those in [registry] are preferred. - */ -@WorkflowUiExperimentalApi -public infix fun ViewEnvironment.merge(registry: ViewRegistry): ViewEnvironment { - if (this[ViewRegistry] === registry) return this - if (registry.keys.isEmpty()) return this - - val merged = this[ViewRegistry] merge registry - return this + merged -} - -/** - * Combines the receiving [ViewEnvironment] with [other], taking care to merge - * their [ViewRegistry] entries. Any other conflicting values in [other] replace those - * in the receiver. - */ -@WorkflowUiExperimentalApi -public infix fun ViewEnvironment.merge(other: ViewEnvironment): ViewEnvironment { - if (this == other) return this - if (other.map.isEmpty()) return this - if (this.map.isEmpty()) return other - - val oldReg = this[ViewRegistry] - val newReg = other[ViewRegistry] - return this + other + (ViewRegistry to oldReg.merge(newReg)) -} diff --git a/workflow-ui/core-common/src/main/java/com/squareup/workflow1/ui/container/EnvironmentScreen.kt b/workflow-ui/core-common/src/main/java/com/squareup/workflow1/ui/container/EnvironmentScreen.kt index e724491ba8..7d73579e10 100644 --- a/workflow-ui/core-common/src/main/java/com/squareup/workflow1/ui/container/EnvironmentScreen.kt +++ b/workflow-ui/core-common/src/main/java/com/squareup/workflow1/ui/container/EnvironmentScreen.kt @@ -5,7 +5,7 @@ import com.squareup.workflow1.ui.Screen import com.squareup.workflow1.ui.ViewEnvironment import com.squareup.workflow1.ui.ViewRegistry import com.squareup.workflow1.ui.WorkflowUiExperimentalApi -import com.squareup.workflow1.ui.merge +import com.squareup.workflow1.ui.plus /** * Pairs a [wrapped] rendering with a [environment] to support its display. @@ -36,7 +36,7 @@ public class EnvironmentScreen( */ @WorkflowUiExperimentalApi public fun Screen.withRegistry(viewRegistry: ViewRegistry): EnvironmentScreen<*> { - return withEnvironment(ViewEnvironment.EMPTY merge viewRegistry) + return withEnvironment(ViewEnvironment.EMPTY + viewRegistry) } /** @@ -53,7 +53,7 @@ public fun Screen.withEnvironment( return when (this) { is EnvironmentScreen<*> -> { if (environment.map.isEmpty()) this - else EnvironmentScreen(wrapped, this.environment merge environment) + else EnvironmentScreen(wrapped, this.environment + environment) } else -> EnvironmentScreen(this, environment) } diff --git a/workflow-ui/core-common/src/test/java/com/squareup/workflow1/ui/ViewEnvironmentTest.kt b/workflow-ui/core-common/src/test/java/com/squareup/workflow1/ui/ViewEnvironmentTest.kt index 9b2499ba77..063aee10f3 100644 --- a/workflow-ui/core-common/src/test/java/com/squareup/workflow1/ui/ViewEnvironmentTest.kt +++ b/workflow-ui/core-common/src/test/java/com/squareup/workflow1/ui/ViewEnvironmentTest.kt @@ -99,4 +99,22 @@ internal class ViewEnvironmentTest { val environment = EMPTY + (StringHint to "able") assertThat(environment + environment).isSameInstanceAs(environment) } + + @Test fun `honors combine`() { + val combiningHint = object : ViewEnvironmentKey(String::class) { + override val default: String + get() = error("") + + override fun combine( + left: String, + right: String + ): String { + return "$left-$right" + } + } + + val left = EMPTY + (combiningHint to "able") + val right = EMPTY + (combiningHint to "baker") + assertThat((left + right)[combiningHint]).isEqualTo("able-baker") + } } diff --git a/workflow-ui/core-common/src/test/java/com/squareup/workflow1/ui/ViewRegistryTest.kt b/workflow-ui/core-common/src/test/java/com/squareup/workflow1/ui/ViewRegistryTest.kt index eff9e68b19..45b1b7c327 100644 --- a/workflow-ui/core-common/src/test/java/com/squareup/workflow1/ui/ViewRegistryTest.kt +++ b/workflow-ui/core-common/src/test/java/com/squareup/workflow1/ui/ViewRegistryTest.kt @@ -60,22 +60,27 @@ internal class ViewRegistryTest { assertThat(merged[FooRendering::class]).isSameInstanceAs(factory2) } - @Test fun `merge into ViewEnvironment prefers right side`() { - val factory1 = TestEntry(FooRendering::class) - val factory2 = TestEntry(FooRendering::class) - val merged = (EMPTY + ViewRegistry(factory1)) merge ViewRegistry(factory2) + @Test fun `ViewEnvironment plus ViewRegistry prefers new registry values`() { + val leftBar = TestEntry(BarRendering::class) + val rightBar = TestEntry(BarRendering::class) + + val env = EMPTY + ViewRegistry(leftBar) + val merged = env + ViewRegistry(rightBar, TestEntry(FooRendering::class)) - assertThat(merged[ViewRegistry][FooRendering::class]).isSameInstanceAs(factory2) + assertThat(merged[ViewRegistry][BarRendering::class]).isSameInstanceAs(rightBar) + assertThat(merged[ViewRegistry][FooRendering::class]).isNotNull() } - @Test fun `merge of ViewEnvironments prefers right side`() { - val factory1 = TestEntry(FooRendering::class) - val factory2 = TestEntry(FooRendering::class) - val e1 = EMPTY + ViewRegistry(factory1) - val e2 = EMPTY + ViewRegistry(factory2) - val merged = e1 + e2 + @Test fun `ViewEnvironment plus ViewEnvironment prefers right ViewRegistry`() { + val leftBar = TestEntry(BarRendering::class) + val rightBar = TestEntry(BarRendering::class) + + val leftEnv = EMPTY + ViewRegistry(leftBar) + val rightEnv = EMPTY + ViewRegistry(rightBar, TestEntry(FooRendering::class)) + val merged = leftEnv + rightEnv - assertThat(merged[ViewRegistry][FooRendering::class]).isSameInstanceAs(factory2) + assertThat(merged[ViewRegistry][BarRendering::class]).isSameInstanceAs(rightBar) + assertThat(merged[ViewRegistry][FooRendering::class]).isNotNull() } @Test fun `plus of empty returns this`() { @@ -98,21 +103,6 @@ internal class ViewRegistryTest { assertThat(ViewRegistry() merge reg).isSameInstanceAs(reg) } - @Test fun `env merge of empty reg returns this env`() { - val env = EMPTY + ViewRegistry(TestEntry(FooRendering::class)) - assertThat(env merge ViewRegistry()).isSameInstanceAs(env) - } - - @Test fun `env merge of empty env returns other env`() { - val env = EMPTY + ViewRegistry(TestEntry(FooRendering::class)) - assertThat(env merge EMPTY).isSameInstanceAs(env) - } - - @Test fun `env merge to empty env returns other env`() { - val env = EMPTY + ViewRegistry(TestEntry(FooRendering::class)) - assertThat(EMPTY merge env).isSameInstanceAs(env) - } - @Test fun `env plus empty reg returns env`() { val env = EMPTY + ViewRegistry(TestEntry(FooRendering::class)) assertThat(env + ViewRegistry()).isSameInstanceAs(env) @@ -136,17 +126,6 @@ internal class ViewRegistryTest { assertThat(reg merge reg).isSameInstanceAs(reg) } - @Test fun `env merges same reg returns self`() { - val reg = ViewRegistry(TestEntry(FooRendering::class)) - val env = EMPTY + reg - assertThat(env merge reg).isSameInstanceAs(env) - } - - @Test fun `env merges self reg returns self`() { - val env = EMPTY + ViewRegistry(TestEntry(FooRendering::class)) - assertThat(env merge env).isSameInstanceAs(env) - } - private class TestEntry( override val type: KClass ) : Entry