Skip to content

Commit f2146a3

Browse files
authored
bugfix: correct nullability semantics around generation and usage of struct members (#710)
1 parent 57bd7ee commit f2146a3

File tree

5 files changed

+39
-6
lines changed

5 files changed

+39
-6
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"id": "da10a905-d84c-45bf-bc34-520ab90d9285",
3+
"type": "bugfix",
4+
"description": "Fix inconsistent nullability semantics when generating struct members."
5+
}

gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jsoupVersion=1.14.3
2424
okHttpVersion=5.0.0-alpha.10
2525

2626
# codegen
27-
smithyVersion=1.25.0
27+
smithyVersion=1.25.2
2828
smithyGradleVersion=0.6.0
2929

3030
# testing/utility
@@ -46,4 +46,4 @@ kotlinLoggingVersion=2.1.21
4646
slf4jVersion=1.7.36
4747

4848
# crt
49-
crtKotlinVersion=0.6.4
49+
crtKotlinVersion=0.6.4

smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/core/KotlinSymbolProvider.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ class KotlinSymbolProvider(private val model: Model, private val settings: Kotli
170170
val targetShape =
171171
model.getShape(shape.target).orElseThrow { CodegenException("Shape not found: ${shape.target}") }
172172

173-
val targetSymbol = if (nullableIndex.isMemberNullable(shape, NullableIndex.CheckMode.CLIENT_ZERO_VALUE_V1)) {
173+
val targetSymbol = if (nullableIndex.isMemberNullable(shape, NullableIndex.CheckMode.CLIENT_ZERO_VALUE_V1_NO_INPUT)) {
174174
toSymbol(targetShape).toBuilder().boxed().build()
175175
} else {
176176
toSymbol(targetShape)

smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/rendering/StructureGenerator.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import software.amazon.smithy.codegen.core.Symbol
99
import software.amazon.smithy.kotlin.codegen.core.*
1010
import software.amazon.smithy.kotlin.codegen.lang.KotlinTypes
1111
import software.amazon.smithy.kotlin.codegen.model.*
12-
import software.amazon.smithy.model.knowledge.NullableIndex
1312
import software.amazon.smithy.model.shapes.*
1413
import software.amazon.smithy.model.traits.ErrorTrait
1514
import software.amazon.smithy.model.traits.HttpLabelTrait
@@ -28,7 +27,6 @@ class StructureGenerator(
2827
private val symbolProvider = ctx.symbolProvider
2928
private val model = ctx.model
3029
private val symbol = ctx.symbolProvider.toSymbol(ctx.shape)
31-
private val nullableIndex = NullableIndex(ctx.model)
3230

3331
fun render() {
3432
writer.renderDocumentation(shape)
@@ -148,7 +146,7 @@ class StructureGenerator(
148146
// Return the appropriate hashCode fragment based on ShapeID of member target.
149147
private fun selectHashFunctionForShape(member: MemberShape): String {
150148
val targetShape = model.expectShape(member.target)
151-
val isNullable = nullableIndex.isMemberNullable(member, NullableIndex.CheckMode.CLIENT_ZERO_VALUE_V1_NO_INPUT)
149+
val isNullable = memberNameSymbolIndex[member]!!.second.isBoxed
152150
return when (targetShape.type) {
153151
ShapeType.INTEGER ->
154152
when (isNullable) {

smithy-kotlin-codegen/src/test/kotlin/software/amazon/smithy/kotlin/codegen/rendering/StructureGeneratorTest.kt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,36 @@ class StructureGeneratorTest {
644644
contents.shouldContainOnlyOnceWithDiff(expectedEqualsContent)
645645
contents.shouldContainOnlyOnceWithDiff(expectedHashCodeContent)
646646
}
647+
648+
@Test
649+
fun testNullableReferences() {
650+
val model = """
651+
structure Struct {
652+
aInt: Integer
653+
@default(0)
654+
bInt: Integer
655+
}
656+
"""
657+
.trimIndent()
658+
.prependNamespaceAndService(version = "2.0")
659+
.toSmithyModel()
660+
661+
val provider: SymbolProvider = KotlinCodegenPlugin.createSymbolProvider(model)
662+
val writer = KotlinWriter(TestModelDefault.NAMESPACE)
663+
val struct = model.expectShape<StructureShape>("com.test#Struct")
664+
val renderingCtx = RenderingContext(writer, struct, model, provider, model.defaultSettings())
665+
StructureGenerator(renderingCtx).render()
666+
667+
val generated = writer.toString()
668+
val expected = """
669+
override fun hashCode(): kotlin.Int {
670+
var result = aInt ?: 0
671+
result = 31 * result + (bInt)
672+
return result
673+
}
674+
""".formatForTest()
675+
generated.shouldContainOnlyOnceWithDiff(expected)
676+
}
647677
}
648678

649679
private fun String?.indent(indentation: String = " "): String? = if (this == null) null else "$indentation$this"

0 commit comments

Comments
 (0)