Skip to content

Commit

Permalink
improve when explicit null checking is required
Browse files Browse the repository at this point in the history
  • Loading branch information
aajtodd committed Sep 28, 2023
1 parent 94a43d9 commit 8933b17
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ data class KotlinSettings(
* @return Returns the extracted settings
*/
fun from(model: Model, config: ObjectNode): KotlinSettings {
config.warnIfAdditionalProperties(listOf(SERVICE, PACKAGE_SETTINGS, BUILD_SETTINGS, SDK_ID))
config.warnIfAdditionalProperties(listOf(SERVICE, PACKAGE_SETTINGS, BUILD_SETTINGS, SDK_ID, API_SETTINGS))

val serviceId = config.getStringMember(SERVICE)
.map(StringNode::expectShapeId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ object SymbolProperty {
const val FULLY_QUALIFIED_NAME_HINT: String = "fullyQualifiedNameHint"
}

/**
* Test if a symbol is required (not-nullable) with no default value set. This means there is no builder
* set default so the constructor will have to generate a runtime check that a value is set.
*/
val Symbol.isRequiredWithNoDefault: Boolean
get() = !isNullable && defaultValue() == null

/**
* Test if a symbol is nullable
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,26 +85,25 @@ class StructureGenerator(
"public"
}

when {
memberShape.isRequiredInStruct && !memberSymbol.isNullable -> {
writer.write(
"""#1L val #2L: #3F = requireNotNull(builder.#2L) { "A non-null value must be provided for #2L" }""",
prefix,
if (memberShape.isRequiredInStruct && memberSymbol.isRequiredWithNoDefault) {
writer.write(
"""#1L val #2L: #3F = requireNotNull(builder.#2L) { "A non-null value must be provided for #2L" }""",
prefix,
memberName,
memberSymbol,
)
} else {
writer.write("#1L val #2L: #3F = builder.#2L", prefix, memberName, memberSymbol)
}

if (memberShape.isNonBlankInStruct) {
writer
.indent()
.write(
""".apply { require(isNotBlank()) { "A non-blank value must be provided for #L" } }""",
memberName,
memberSymbol,
)
if (memberShape.isNonBlankInStruct) {
writer
.indent()
.write(
""".apply { require(isNotBlank()) { "A non-blank value must be provided for #L" } }""",
memberName,
)
.dedent()
}
}

else -> writer.write("#1L val #2L: #3F = builder.#2L", prefix, memberName, memberSymbol)
.dedent()
}
}

Expand Down Expand Up @@ -248,7 +247,7 @@ class StructureGenerator(
val (memberName, memberSymbol) = memberNameSymbolIndex[member]!!
writer.renderMemberDocumentation(model, member)
writer.renderAnnotations(member)
val builderMemberSymbol = if (!memberSymbol.isNullable && memberSymbol.defaultValue() == null) {
val builderMemberSymbol = if (memberSymbol.isRequiredWithNoDefault) {
// nullabilty is w.r.t to the immmutable property type, builders have to account for the user
// providing required values though and thus must be nullable. They are then checked
// at runtime in the ctor to ensure a value was provided
Expand Down Expand Up @@ -299,7 +298,11 @@ class StructureGenerator(
"}",
) {
sortedMembers
.filter(MemberShape::isRequired)
.filter {
val (_, memberSymbol) = memberNameSymbolIndex[it]!!
// required members with no default
memberSymbol.isRequiredWithNoDefault
}
.filterNot {
val target = ctx.model.expectShape(it.target)
target.isStreaming || it.hasTrait<ClientOptionalTrait>()
Expand Down

0 comments on commit 8933b17

Please sign in to comment.