Skip to content

Commit

Permalink
Use the default(..) trait to source default information
Browse files Browse the repository at this point in the history
  • Loading branch information
rcoh committed Sep 12, 2023
1 parent 7bf8837 commit 059aa70
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package software.amazon.smithy.rust.codegen.core.smithy

import software.amazon.smithy.codegen.core.Symbol
import software.amazon.smithy.model.node.Node
import software.amazon.smithy.model.shapes.Shape
import software.amazon.smithy.rust.codegen.core.rustlang.RustModule
import software.amazon.smithy.rust.codegen.core.rustlang.RustType
Expand Down Expand Up @@ -102,6 +103,8 @@ sealed class Default {
* This symbol should use the Rust `std::default::Default` when unset
*/
object RustDefault : Default()

data class NonZeroDefault(val value: Node) : Default()
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import software.amazon.smithy.codegen.core.SymbolProvider
import software.amazon.smithy.model.Model
import software.amazon.smithy.model.knowledge.NullableIndex
import software.amazon.smithy.model.knowledge.NullableIndex.CheckMode
import software.amazon.smithy.model.node.Node
import software.amazon.smithy.model.shapes.BigDecimalShape
import software.amazon.smithy.model.shapes.BigIntegerShape
import software.amazon.smithy.model.shapes.BlobShape
Expand Down Expand Up @@ -37,6 +38,7 @@ import software.amazon.smithy.model.shapes.StringShape
import software.amazon.smithy.model.shapes.StructureShape
import software.amazon.smithy.model.shapes.TimestampShape
import software.amazon.smithy.model.shapes.UnionShape
import software.amazon.smithy.model.traits.DefaultTrait
import software.amazon.smithy.model.traits.EnumTrait
import software.amazon.smithy.model.traits.ErrorTrait
import software.amazon.smithy.rust.codegen.core.rustlang.Attribute
Expand All @@ -48,6 +50,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.traits.RustBoxTrait
import software.amazon.smithy.rust.codegen.core.util.PANIC
import software.amazon.smithy.rust.codegen.core.util.hasTrait
import software.amazon.smithy.rust.codegen.core.util.letIf
import software.amazon.smithy.rust.codegen.core.util.orNull
import software.amazon.smithy.rust.codegen.core.util.toPascalCase
import software.amazon.smithy.rust.codegen.core.util.toSnakeCase
import kotlin.reflect.KClass
Expand Down Expand Up @@ -79,16 +82,18 @@ data class MaybeRenamed(val name: String, val renamedFrom: String?)
/**
* Make the return [value] optional if the [member] symbol is as well optional.
*/
fun SymbolProvider.wrapOptional(member: MemberShape, value: String): String = value.letIf(toSymbol(member).isOptional()) {
"Some($value)"
}
fun SymbolProvider.wrapOptional(member: MemberShape, value: String): String =
value.letIf(toSymbol(member).isOptional()) {
"Some($value)"
}

/**
* Make the return [value] optional if the [member] symbol is not optional.
*/
fun SymbolProvider.toOptional(member: MemberShape, value: String): String = value.letIf(!toSymbol(member).isOptional()) {
"Some($value)"
}
fun SymbolProvider.toOptional(member: MemberShape, value: String): String =
value.letIf(!toSymbol(member).isOptional()) {
"Some($value)"
}

/**
* Services can rename their contained shapes. See https://awslabs.github.io/smithy/1.0/spec/core/model.html#service
Expand Down Expand Up @@ -170,7 +175,7 @@ open class SymbolVisitor(
}

private fun simpleShape(shape: SimpleShape): Symbol {
return symbolBuilder(shape, SimpleShapes.getValue(shape::class)).setDefault(Default.RustDefault).build()
return symbolBuilder(shape, SimpleShapes.getValue(shape::class)).build()
}

override fun booleanShape(shape: BooleanShape): Symbol = simpleShape(shape)
Expand Down Expand Up @@ -263,13 +268,21 @@ open class SymbolVisitor(

override fun memberShape(shape: MemberShape): Symbol {
val target = model.expectShape(shape.target)
val defaultValue = shape.getMemberTrait(model, DefaultTrait::class.java).orNull()?.let { trait ->
when (val value = trait.toNode()) {
Node.from(""), Node.from(0), Node.from(false), Node.arrayNode(), Node.objectNode() -> Default.RustDefault
Node.nullNode() -> Default.NoDefault
else -> { Default.NonZeroDefault(value)
}
}
} ?: Default.NoDefault
// Handle boxing first, so we end up with Option<Box<_>>, not Box<Option<_>>.
return handleOptionality(
handleRustBoxing(toSymbol(target), shape),
shape,
nullableIndex,
config.nullabilityCheckMode,
)
).toBuilder().setDefault(defaultValue).build()
}

override fun timestampShape(shape: TimestampShape?): Symbol {
Expand Down Expand Up @@ -297,7 +310,12 @@ fun symbolBuilder(shape: Shape?, rustType: RustType): Symbol.Builder =
// If we ever generate a `thisisabug.rs`, there is a bug in our symbol generation
.definitionFile("thisisabug.rs")

fun handleOptionality(symbol: Symbol, member: MemberShape, nullableIndex: NullableIndex, nullabilityCheckMode: CheckMode): Symbol =
fun handleOptionality(
symbol: Symbol,
member: MemberShape,
nullableIndex: NullableIndex,
nullabilityCheckMode: CheckMode,
): Symbol =
symbol.letIf(nullableIndex.isMemberNullable(member, nullabilityCheckMode)) { symbol.makeOptional() }

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import software.amazon.smithy.rust.codegen.core.util.hasTrait
import software.amazon.smithy.rust.codegen.core.util.letIf
import software.amazon.smithy.rust.codegen.core.util.redactIfNecessary
import software.amazon.smithy.rust.codegen.core.util.toSnakeCase
import java.util.logging.Logger

// TODO(https://github.com/awslabs/smithy-rs/issues/1401) This builder generator is only used by the client.
// Move this entire file, and its tests, to `codegen-client`.
Expand Down Expand Up @@ -390,10 +391,15 @@ class BuilderGenerator(
// Write the modifier
when {
!memberSymbol.isOptional() && default == Default.RustDefault -> rust(".unwrap_or_default()")
!memberSymbol.isOptional() -> withBlock(
".ok_or_else(||",
")?",
) { missingRequiredField(memberName) }
!memberSymbol.isOptional() -> {
if (default is Default.NonZeroDefault) {
Logger.getLogger("BuilderGenerator").warning("Shape had a non zero default. Non-zero defaults are not currently supported")
}
withBlock(
".ok_or_else(||",
")?",
) { missingRequiredField(memberName) }
}
}
}
}
Expand Down

0 comments on commit 059aa70

Please sign in to comment.