From 6bd3d9ef8629cbbfba0b406124ac6e8ec7c87d46 Mon Sep 17 00:00:00 2001 From: Jake Wharton Date: Wed, 25 Oct 2023 17:42:41 -0400 Subject: [PATCH] Split ProtocolNodeFactory from ProtocolNode (#1634) Annotate ProtocolNode as codegen API as it always should have been. --- .../redwood/protocol/widget/ProtocolBridge.kt | 5 ++- .../redwood/protocol/widget/ProtocolNode.kt | 17 ++------- .../protocol/widget/ProtocolNodeFactory.kt | 35 +++++++++++++++++++ .../widget/ProtocolNodeFactoryTest.kt | 2 ++ .../kotlin/app/cash/redwood/annotations.kt | 3 +- .../app/cash/redwood/tooling/codegen/types.kt | 2 +- .../codegen/widgetProtocolGeneration.kt | 2 ++ .../redwood/treehouse/TreehouseAppContent.kt | 4 +-- .../cash/redwood/treehouse/TreehouseView.kt | 4 +-- 9 files changed, 52 insertions(+), 22 deletions(-) create mode 100644 redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/ProtocolNodeFactory.kt diff --git a/redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/ProtocolBridge.kt b/redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/ProtocolBridge.kt index ac51de2f3b..7fe06ac437 100644 --- a/redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/ProtocolBridge.kt +++ b/redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/ProtocolBridge.kt @@ -16,6 +16,7 @@ package app.cash.redwood.protocol.widget import app.cash.redwood.Modifier +import app.cash.redwood.RedwoodCodegenApi import app.cash.redwood.protocol.Change import app.cash.redwood.protocol.ChangesSink import app.cash.redwood.protocol.ChildrenChange @@ -40,10 +41,11 @@ import kotlin.native.ObjCName * [PropertyChange]s and [ModifierChange]s are forwarded to their respective widgets. * Events from widgets are forwarded to [eventSink]. */ +@OptIn(RedwoodCodegenApi::class) @ObjCName("ProtocolBridge", exact = true) public class ProtocolBridge( container: Widget.Children, - private val factory: ProtocolNode.Factory, + private val factory: ProtocolNodeFactory, private val eventSink: EventSink, ) : ChangesSink { private val nodes = mutableMapOf>( @@ -120,6 +122,7 @@ public class ProtocolBridge( } } +@OptIn(RedwoodCodegenApi::class) private class RootProtocolNode( private val children: Widget.Children, ) : ProtocolNode, Widget { diff --git a/redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/ProtocolNode.kt b/redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/ProtocolNode.kt index cc0fe55f14..468536a496 100644 --- a/redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/ProtocolNode.kt +++ b/redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/ProtocolNode.kt @@ -15,20 +15,19 @@ */ package app.cash.redwood.protocol.widget +import app.cash.redwood.RedwoodCodegenApi import app.cash.redwood.protocol.ChildrenTag import app.cash.redwood.protocol.EventSink import app.cash.redwood.protocol.ModifierElement import app.cash.redwood.protocol.PropertyChange -import app.cash.redwood.protocol.WidgetTag import app.cash.redwood.widget.Widget -import kotlin.native.ObjCName /** * A node which consumes protocol changes and applies them to a platform-specific representation. * * @suppress */ -@ObjCName("ProtocolNode", exact = true) +@RedwoodCodegenApi public interface ProtocolNode { public val widget: Widget @@ -51,16 +50,4 @@ public interface ProtocolNode { * continue executing. */ public fun children(tag: ChildrenTag): Widget.Children? - - @ObjCName("ProtocolNodeFactory", exact = true) - public interface Factory { - /** - * Create a new protocol node of the specified [tag]. - * - * Invalid [tag] values can either produce an exception or result in `null` being returned. - * If `null` is returned, the caller should make every effort to ignore this node and - * continue executing. - */ - public fun create(tag: WidgetTag): ProtocolNode? - } } diff --git a/redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/ProtocolNodeFactory.kt b/redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/ProtocolNodeFactory.kt new file mode 100644 index 0000000000..affef094e8 --- /dev/null +++ b/redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/ProtocolNodeFactory.kt @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2021 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package app.cash.redwood.protocol.widget + +import app.cash.redwood.RedwoodCodegenApi +import app.cash.redwood.protocol.WidgetTag +import kotlin.native.ObjCName + +@ObjCName("ProtocolNodeFactory", exact = true) +public interface ProtocolNodeFactory { + /** + * Create a new protocol node of the specified [tag]. + * + * Invalid [tag] values can either produce an exception or result in `null` being returned. + * If `null` is returned, the caller should make every effort to ignore this node and + * continue executing. + * + * @suppress + */ + @RedwoodCodegenApi + public fun create(tag: WidgetTag): ProtocolNode? +} diff --git a/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/ProtocolNodeFactoryTest.kt b/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/ProtocolNodeFactoryTest.kt index 3d0808ad05..21efb43c0d 100644 --- a/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/ProtocolNodeFactoryTest.kt +++ b/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/ProtocolNodeFactoryTest.kt @@ -16,6 +16,7 @@ package app.cash.redwood.protocol.widget import app.cash.redwood.Modifier +import app.cash.redwood.RedwoodCodegenApi import app.cash.redwood.protocol.ChildrenTag import app.cash.redwood.protocol.Event import app.cash.redwood.protocol.EventSink @@ -45,6 +46,7 @@ import kotlinx.serialization.json.buildJsonArray import kotlinx.serialization.json.buildJsonObject import kotlinx.serialization.modules.SerializersModule +@OptIn(RedwoodCodegenApi::class) class ProtocolNodeFactoryTest { @Test fun unknownWidgetThrowsDefault() { val factory = TestSchemaProtocolNodeFactory( diff --git a/redwood-runtime/src/commonMain/kotlin/app/cash/redwood/annotations.kt b/redwood-runtime/src/commonMain/kotlin/app/cash/redwood/annotations.kt index 04bb289d10..e8f2c48f7a 100644 --- a/redwood-runtime/src/commonMain/kotlin/app/cash/redwood/annotations.kt +++ b/redwood-runtime/src/commonMain/kotlin/app/cash/redwood/annotations.kt @@ -25,7 +25,8 @@ import androidx.compose.runtime.StableMarker public annotation class LayoutScopeMarker /** - * Denote an API which should only be used by Redwood's generated code. + * Denote an API which should only be used by Redwood's generated code and is not considered + * stable across any version. * * @suppress */ diff --git a/redwood-tooling-codegen/src/main/kotlin/app/cash/redwood/tooling/codegen/types.kt b/redwood-tooling-codegen/src/main/kotlin/app/cash/redwood/tooling/codegen/types.kt index 5b4e1562a3..6b8b91f5ea 100644 --- a/redwood-tooling-codegen/src/main/kotlin/app/cash/redwood/tooling/codegen/types.kt +++ b/redwood-tooling-codegen/src/main/kotlin/app/cash/redwood/tooling/codegen/types.kt @@ -54,7 +54,7 @@ internal object WidgetProtocol { val ProtocolMismatchHandler = ClassName("app.cash.redwood.protocol.widget", "ProtocolMismatchHandler") val ProtocolNode = ClassName("app.cash.redwood.protocol.widget", "ProtocolNode") - val ProtocolNodeFactory = ProtocolNode.nestedClass("Factory") + val ProtocolNodeFactory = ClassName("app.cash.redwood.protocol.widget", "ProtocolNodeFactory") } internal object Redwood { diff --git a/redwood-tooling-codegen/src/main/kotlin/app/cash/redwood/tooling/codegen/widgetProtocolGeneration.kt b/redwood-tooling-codegen/src/main/kotlin/app/cash/redwood/tooling/codegen/widgetProtocolGeneration.kt index d169eb13bd..7c082b2637 100644 --- a/redwood-tooling-codegen/src/main/kotlin/app/cash/redwood/tooling/codegen/widgetProtocolGeneration.kt +++ b/redwood-tooling-codegen/src/main/kotlin/app/cash/redwood/tooling/codegen/widgetProtocolGeneration.kt @@ -112,6 +112,7 @@ internal fun generateProtocolNodeFactory( FunSpec.builder("create") .addModifiers(OVERRIDE) .addParameter("tag", Protocol.WidgetTag) + .addAnnotation(Redwood.RedwoodCodegenApi) .returns( WidgetProtocol.ProtocolNode.parameterizedBy(typeVariableW) .copy(nullable = true), @@ -197,6 +198,7 @@ internal fun generateProtocolNode( .addModifiers(INTERNAL) .addTypeVariable(typeVariableW) .addSuperinterface(protocolType) + .addAnnotation(Redwood.RedwoodCodegenApi) .primaryConstructor( FunSpec.constructorBuilder() .addParameter("widget", widgetType) diff --git a/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseAppContent.kt b/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseAppContent.kt index 35cc54b299..ffde25c2ec 100644 --- a/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseAppContent.kt +++ b/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseAppContent.kt @@ -19,7 +19,7 @@ import app.cash.redwood.protocol.Change import app.cash.redwood.protocol.Event import app.cash.redwood.protocol.EventSink import app.cash.redwood.protocol.widget.ProtocolBridge -import app.cash.redwood.protocol.widget.ProtocolNode +import app.cash.redwood.protocol.widget.ProtocolNodeFactory import app.cash.redwood.ui.OnBackPressedCallback import app.cash.redwood.ui.OnBackPressedDispatcher import app.cash.redwood.ui.UiConfiguration @@ -319,7 +319,7 @@ private class ViewContentCodeBinding( factory = view.widgetSystem.widgetFactory( json = json, protocolMismatchHandler = eventPublisher.widgetProtocolMismatchHandler(app), - ) as ProtocolNode.Factory, + ) as ProtocolNodeFactory, eventSink = this, ) diff --git a/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseView.kt b/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseView.kt index e447c16871..74d7ac6c16 100644 --- a/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseView.kt +++ b/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseView.kt @@ -16,7 +16,7 @@ package app.cash.redwood.treehouse import app.cash.redwood.protocol.widget.ProtocolMismatchHandler -import app.cash.redwood.protocol.widget.ProtocolNode +import app.cash.redwood.protocol.widget.ProtocolNodeFactory import app.cash.redwood.widget.RedwoodView import kotlin.native.ObjCName import kotlinx.serialization.json.Json @@ -47,6 +47,6 @@ public interface TreehouseView : RedwoodView { public fun widgetFactory( json: Json, protocolMismatchHandler: ProtocolMismatchHandler, - ): ProtocolNode.Factory + ): ProtocolNodeFactory } }