@@ -8,9 +8,11 @@ import software.amazon.smithy.codegen.core.*
88import software.amazon.smithy.kotlin.codegen.KotlinSettings
99import software.amazon.smithy.kotlin.codegen.lang.kotlinReservedWords
1010import software.amazon.smithy.kotlin.codegen.model.*
11+ import software.amazon.smithy.kotlin.codegen.utils.dq
1112import software.amazon.smithy.model.Model
1213import software.amazon.smithy.model.knowledge.NullableIndex
1314import software.amazon.smithy.model.shapes.*
15+ import software.amazon.smithy.model.traits.DefaultTrait
1416import software.amazon.smithy.model.traits.SparseTrait
1517import software.amazon.smithy.model.traits.StreamingTrait
1618import java.util.logging.Logger
@@ -75,31 +77,29 @@ class KotlinSymbolProvider(private val model: Model, private val settings: Kotli
7577
7678 override fun longShape (shape : LongShape ): Symbol = numberShape(shape, " Long" , " 0L" )
7779
78- override fun floatShape (shape : FloatShape ): Symbol = numberShape(shape, " Float" , " 0. 0f" )
80+ override fun floatShape (shape : FloatShape ): Symbol = numberShape(shape, " Float" , " 0f" )
7981
8082 override fun doubleShape (shape : DoubleShape ): Symbol = numberShape(shape, " Double" , " 0.0" )
8183
8284 private fun numberShape (shape : Shape , typeName : String , defaultValue : String = "0"): Symbol =
83- createSymbolBuilder(shape, typeName, namespace = " kotlin" )
84- .defaultValue(defaultValue)
85- .build()
85+ createSymbolBuilder(shape, typeName, namespace = " kotlin" ).defaultValue(defaultValue).build()
8686
8787 override fun bigIntegerShape (shape : BigIntegerShape ? ): Symbol = createBigSymbol(shape, " BigInteger" )
8888
8989 override fun bigDecimalShape (shape : BigDecimalShape ? ): Symbol = createBigSymbol(shape, " BigDecimal" )
9090
9191 private fun createBigSymbol (shape : Shape ? , symbolName : String ): Symbol =
92- createSymbolBuilder(shape, symbolName, namespace = " java.math" , boxed = true ).build()
92+ createSymbolBuilder(shape, symbolName, namespace = " java.math" , nullable = true ).build()
9393
9494 override fun stringShape (shape : StringShape ): Symbol = if (shape.isEnum) {
9595 createEnumSymbol(shape)
9696 } else {
97- createSymbolBuilder(shape, " String" , boxed = true , namespace = " kotlin" ).build()
97+ createSymbolBuilder(shape, " String" , nullable = true , namespace = " kotlin" ).build()
9898 }
9999
100100 private fun createEnumSymbol (shape : Shape ): Symbol {
101101 val namespace = " $rootNamespace .model"
102- return createSymbolBuilder(shape, shape.defaultName(service), namespace, boxed = true )
102+ return createSymbolBuilder(shape, shape.defaultName(service), namespace, nullable = true )
103103 .definitionFile(" ${shape.defaultName(service)} .kt" )
104104 .build()
105105 }
@@ -110,7 +110,7 @@ class KotlinSymbolProvider(private val model: Model, private val settings: Kotli
110110 override fun structureShape (shape : StructureShape ): Symbol {
111111 val name = shape.defaultName(service)
112112 val namespace = " $rootNamespace .model"
113- val builder = createSymbolBuilder(shape, name, namespace, boxed = true )
113+ val builder = createSymbolBuilder(shape, name, namespace, nullable = true )
114114 .definitionFile(" $name .kt" )
115115
116116 // add a reference to each member symbol
@@ -149,7 +149,7 @@ class KotlinSymbolProvider(private val model: Model, private val settings: Kotli
149149 override fun listShape (shape : ListShape ): Symbol {
150150 val reference = toSymbol(shape.member)
151151 val valueType = if (shape.hasTrait<SparseTrait >()) " ${reference.name} ?" else reference.name
152- return createSymbolBuilder(shape, " List<$valueType >" , boxed = true )
152+ return createSymbolBuilder(shape, " List<$valueType >" , nullable = true )
153153 .addReferences(reference)
154154 .putProperty(SymbolProperty .MUTABLE_COLLECTION_FUNCTION , " mutableListOf<$valueType >" )
155155 .putProperty(SymbolProperty .IMMUTABLE_COLLECTION_FUNCTION , " listOf<$valueType >" )
@@ -160,7 +160,7 @@ class KotlinSymbolProvider(private val model: Model, private val settings: Kotli
160160 val reference = toSymbol(shape.value)
161161 val valueType = if (shape.hasTrait<SparseTrait >()) " ${reference.name} ?" else reference.name
162162
163- return createSymbolBuilder(shape, " Map<String, $valueType >" , boxed = true )
163+ return createSymbolBuilder(shape, " Map<String, $valueType >" , nullable = true )
164164 .addReferences(reference)
165165 .putProperty(SymbolProperty .MUTABLE_COLLECTION_FUNCTION , " mutableMapOf<String, $valueType >" )
166166 .putProperty(SymbolProperty .IMMUTABLE_COLLECTION_FUNCTION , " mapOf<String, $valueType >" )
@@ -172,11 +172,17 @@ class KotlinSymbolProvider(private val model: Model, private val settings: Kotli
172172 val targetShape =
173173 model.getShape(shape.target).orElseThrow { CodegenException (" Shape not found: ${shape.target} " ) }
174174
175- val targetSymbol = if (nullableIndex.isMemberNullable(shape, NullableIndex .CheckMode .CLIENT_ZERO_VALUE_V1_NO_INPUT )) {
176- toSymbol(targetShape).toBuilder().boxed().build()
177- } else {
178- toSymbol(targetShape)
179- }
175+ val targetSymbol = toSymbol(targetShape)
176+ .toBuilder()
177+ .apply {
178+ if (nullableIndex.isMemberNullable(shape, NullableIndex .CheckMode .CLIENT_ZERO_VALUE_V1_NO_INPUT )) nullable()
179+
180+ shape.getTrait<DefaultTrait >()?.let {
181+ defaultValue(it.getDefaultValue(targetShape), DefaultValueType .MODELED )
182+ }
183+ }
184+ .build()
185+
180186 // figure out if we are referencing an event stream or not.
181187 // NOTE: unlike blob streams we actually re-use the target (union) shape which is why we can't do this
182188 // when visiting a unionShape() like we can for blobShape()
@@ -197,9 +203,18 @@ class KotlinSymbolProvider(private val model: Model, private val settings: Kotli
197203 }
198204 }
199205
206+ private fun DefaultTrait.getDefaultValue (targetShape : Shape ): String? = when {
207+ toNode().toString() == " null" || targetShape is BlobShape && toNode().toString() == " " -> null
208+ toNode().isNumberNode -> getDefaultValueForNumber(targetShape, toNode().toString())
209+ toNode().isArrayNode -> " listOf()"
210+ toNode().isObjectNode -> " mapOf()"
211+ toNode().isStringNode -> toNode().toString().dq()
212+ else -> toNode().toString()
213+ }
214+
200215 override fun timestampShape (shape : TimestampShape ? ): Symbol {
201216 val dependency = KotlinDependency .CORE
202- return createSymbolBuilder(shape, " Instant" , boxed = true )
217+ return createSymbolBuilder(shape, " Instant" , nullable = true )
203218 .namespace(" ${dependency.namespace} .time" , " ." )
204219 .addDependency(dependency)
205220 .build()
@@ -208,7 +223,7 @@ class KotlinSymbolProvider(private val model: Model, private val settings: Kotli
208223 override fun blobShape (shape : BlobShape ): Symbol = if (shape.hasTrait<StreamingTrait >()) {
209224 RuntimeTypes .Core .Content .ByteStream .asNullable()
210225 } else {
211- createSymbolBuilder(shape, " ByteArray" , boxed = true , namespace = " kotlin" ).build()
226+ createSymbolBuilder(shape, " ByteArray" , nullable = true , namespace = " kotlin" ).build()
212227 }
213228
214229 override fun documentShape (shape : DocumentShape ? ): Symbol =
@@ -217,7 +232,7 @@ class KotlinSymbolProvider(private val model: Model, private val settings: Kotli
217232 override fun unionShape (shape : UnionShape ): Symbol {
218233 val name = shape.defaultName(service)
219234 val namespace = " $rootNamespace .model"
220- val builder = createSymbolBuilder(shape, name, namespace, boxed = true )
235+ val builder = createSymbolBuilder(shape, name, namespace, nullable = true )
221236 .definitionFile(" $name .kt" )
222237
223238 // add a reference to each member symbol
@@ -243,16 +258,23 @@ class KotlinSymbolProvider(private val model: Model, private val settings: Kotli
243258 /* *
244259 * Creates a symbol builder for the shape with the given type name in the root namespace.
245260 */
246- private fun createSymbolBuilder (shape : Shape ? , typeName : String , boxed : Boolean = false): Symbol .Builder {
261+ private fun createSymbolBuilder (shape : Shape ? , typeName : String , nullable : Boolean = false): Symbol .Builder {
247262 val builder = Symbol .builder()
248263 .putProperty(SymbolProperty .SHAPE_KEY , shape)
249264 .name(typeName)
250- if (boxed ) {
251- builder.boxed ()
265+ if (nullable ) {
266+ builder.nullable ()
252267 }
253268 return builder
254269 }
255270
271+ private fun getDefaultValueForNumber (shape : Shape , value : String ) = when (shape) {
272+ is LongShape -> " ${value} L"
273+ is FloatShape -> " ${value} f"
274+ is DoubleShape -> if (value.matches(" [0-9]*\\ .[0-9]+" .toRegex())) value else " $value .0"
275+ else -> value
276+ }
277+
256278 /* *
257279 * Creates a symbol builder for the shape with the given type name in a child namespace relative
258280 * to the root namespace e.g. `relativeNamespace = bar` with a root namespace of `foo` would set
@@ -262,8 +284,8 @@ class KotlinSymbolProvider(private val model: Model, private val settings: Kotli
262284 shape : Shape ? ,
263285 typeName : String ,
264286 namespace : String ,
265- boxed : Boolean = false,
266- ): Symbol .Builder = createSymbolBuilder(shape, typeName, boxed ).namespace(namespace, " ." )
287+ nullable : Boolean = false,
288+ ): Symbol .Builder = createSymbolBuilder(shape, typeName, nullable ).namespace(namespace, " ." )
267289}
268290
269291// Add a reference and it's children
0 commit comments