Skip to content

Commit

Permalink
Respect event type nullability
Browse files Browse the repository at this point in the history
If an event is declared as non-nullable then it is required and non-null. If an event is declared as nullable then it is still required but can be set to null. And, of course, nullable event can have a default of null.

This brings it directly in line with property behavior. I'm not sure why we had the weird nullability behavior from before.
  • Loading branch information
JakeWharton committed Apr 18, 2023
1 parent c56178a commit ba0f5a3
Show file tree
Hide file tree
Showing 12 changed files with 46 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -342,14 +342,14 @@ class DiffConsumingNodeFactoryTest {
var onChange: ((String) -> Unit)? = null
private set

override fun onChange(onChange: ((String) -> Unit)?) {
override fun onChange(onChange: (String) -> Unit) {
this.onChange = onChange
}

var onChangeCustomType: ((Duration) -> Unit)? = null
private set

override fun onChangeCustomType(onChangeCustomType: ((Duration) -> Unit)?) {
override fun onChangeCustomType(onChangeCustomType: (Duration) -> Unit) {
this.onChangeCustomType = onChangeCustomType
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@ internal fun generateComposable(
}
is Event -> {
ParameterSpec.builder(trait.name, trait.lambdaType)
.defaultValue(trait.defaultExpression ?: "null")
.apply {
trait.defaultExpression?.let { defaultValue(it) }
}
.build()
}
is Children -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ internal fun generateProtocolWidget(
}
is ProtocolEvent -> {
addProperty(
PropertySpec.builder(trait.name, trait.lambdaType, PRIVATE)
PropertySpec.builder(trait.name, trait.lambdaType.copy(nullable = true), PRIVATE)
.mutable()
.initializer("null")
.build(),
Expand All @@ -359,16 +359,24 @@ internal fun generateProtocolWidget(
FunSpec.builder(trait.name)
.addModifiers(OVERRIDE)
.addParameter(trait.name, trait.lambdaType)
.addStatement("val %1NSet = %1N != null", trait.name)
.beginControlFlow("if (%1NSet != (this.%1N != null))", trait.name)
.addStatement(
"this.state.append(%T(this.id, %T(%L), %M(%NSet)))",
Protocol.PropertyDiff,
Protocol.PropertyTag,
trait.tag,
KotlinxSerialization.JsonPrimitive,
trait.name,
)
.apply {
val newValue = if (trait.isNullable) {
addStatement("val %1NSet = %1N != null", trait.name)
beginControlFlow("if (%1NSet != (this.%1N != null))", trait.name)
trait.name + "Set"
} else {
beginControlFlow("if (this.%1N == null)", trait.name)
"true"
}
addStatement(
"this.state.append(%T(this.id, %T(%L), %M(%L)))",
Protocol.PropertyDiff,
Protocol.PropertyTag,
trait.tag,
KotlinxSerialization.JsonPrimitive,
newValue,
)
}
.endControlFlow()
.addStatement("this.%1N = %1N", trait.name)
.build(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,11 @@ internal fun generateDiffConsumingWidget(
)
}
nextControlFlow("else")
addStatement("null")
if (trait.isNullable) {
addStatement("null")
} else {
addStatement("throw %T()", Stdlib.AssertionError)
}
endControlFlow()
addStatement("widget.%1N(%1N)", trait.name)
endControlFlow()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,16 @@ internal val FqType.flatName: String

internal val Event.lambdaType: TypeName
get() {
parameterType?.let { parameterType ->
return LambdaTypeName.get(null, parameterType.asTypeName(), returnType = UNIT)
.copy(nullable = true)
}
return noArgumentEventLambda
val lambda = parameterType
?.let { parameterType ->
LambdaTypeName.get(null, parameterType.asTypeName(), returnType = UNIT)
}
?: noArgumentEventLambda

return lambda.copy(nullable = isNullable)
}

private val noArgumentEventLambda = LambdaTypeName.get(returnType = UNIT).copy(nullable = true)
private val noArgumentEventLambda = LambdaTypeName.get(returnType = UNIT)

internal fun Schema.composePackage(host: Schema? = null): String {
return if (host == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class ComposeGenerationTest {
val fileSpec = generateComposable(schema, schema.widgets.single())
assertThat(fileSpec.toString()).apply {
contains("trait: String = \"test\"")
contains("onEvent: (() -> Unit)? = { error(\"test\") }")
contains("onEvent: () -> Unit = { error(\"test\") }")
contains("block: @Composable () -> Unit = {}")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,15 @@ class TestingGenerationTest {
| this.trait = trait
| }
|
| public override fun onEvent(onEvent: (() -> Unit)?): Unit {
| public override fun onEvent(onEvent: () -> Unit): Unit {
| this.onEvent = onEvent
| }
|
| public override fun snapshot(): TestingGenerationTestBasicWidgetValue =
| TestingGenerationTestBasicWidgetValue(
| layoutModifiers = layoutModifiers,
| trait = trait!!,
| onEvent = onEvent,
| onEvent = onEvent!!,
| block = block.map { it.`value`.snapshot() },
| )
|}
Expand All @@ -119,7 +119,7 @@ class TestingGenerationTest {
|public class TestingGenerationTestBasicWidgetValue(
| public override val layoutModifiers: LayoutModifier = LayoutModifier,
| public val trait: String = "test",
| public val onEvent: (() -> Unit)? = { error("test") },
| public val onEvent: () -> Unit = { error("test") },
| public val block: List<WidgetValue> = listOf(),
|) : WidgetValue {
| public override val childrenLists: List<List<WidgetValue>>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ public interface Widget {

public interface Event : Trait {
public val parameterType: FqType?
public val isNullable: Boolean
}

public interface Children : Trait {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ internal data class ParsedProtocolEvent(
override val tag: Int,
override val name: String,
override val parameterType: FqType?,
override val isNullable: Boolean,
override val defaultExpression: String? = null,
override val deprecation: ParsedDeprecation? = null,
) : ProtocolEvent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ private fun parseWidget(
tag = property.tag,
name = it.name!!,
parameterType = arguments.singleOrNull()?.type?.toFqType(),
isNullable = it.type.isMarkedNullable,
defaultExpression = defaultExpression,
deprecation = deprecation,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ data class TextInput(
val hint: String,
@Property(3)
@Default("null")
val onChange: (TextFieldState) -> Unit,
val onChange: ((TextFieldState) -> Unit)?,
)

@Widget(2)
Expand Down
2 changes: 1 addition & 1 deletion test-schema/src/main/kotlin/example/redwood/schema.kt
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public data class Text(
@Widget(4)
public data class Button(
@Property(1) val text: String?,
@Property(2) val onClick: () -> Unit,
@Property(2) val onClick: (() -> Unit)?,
)

@Widget(5)
Expand Down

0 comments on commit ba0f5a3

Please sign in to comment.