Skip to content

Commit 6b627c7

Browse files
aajtoddmilesziemer
andauthored
Remove defaults for some shapes in some services (smithy-lang#1116)
Adds an integration that removes the default value from certain shapes in some services where the default value is 0, but the service expects a value > 0. Co-authored-by: Miles Ziemer <mziemer@amazon.com>
1 parent e2030f2 commit 6b627c7

File tree

3 files changed

+151
-0
lines changed

3 files changed

+151
-0
lines changed
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package aws.sdk.kotlin.codegen.customization
7+
8+
import software.amazon.smithy.codegen.core.CodegenException
9+
import software.amazon.smithy.kotlin.codegen.KotlinSettings
10+
import software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration
11+
import software.amazon.smithy.kotlin.codegen.model.hasTrait
12+
import software.amazon.smithy.model.Model
13+
import software.amazon.smithy.model.shapes.AbstractShapeBuilder
14+
import software.amazon.smithy.model.shapes.MemberShape
15+
import software.amazon.smithy.model.shapes.Shape
16+
import software.amazon.smithy.model.shapes.ShapeId
17+
import software.amazon.smithy.model.traits.DefaultTrait
18+
import software.amazon.smithy.model.transform.ModelTransformer
19+
import software.amazon.smithy.utils.ToSmithyBuilder
20+
21+
/**
22+
* Removes the default value of certain shapes, and any member that target
23+
* those shapes,for certain services. These default values may cause
24+
* serialization, validation, or other unexpected issues.
25+
*/
26+
class RemoveDefaults : KotlinIntegration {
27+
// Service shape id -> Shape id of each root shape to remove default values from.
28+
private val removeDefaultsFrom = mapOf(
29+
ShapeId.from("com.amazonaws.amplifyuibuilder#AmplifyUIBuilder") to setOf(
30+
ShapeId.from("com.amazonaws.amplifyuibuilder#ListComponentsLimit"),
31+
ShapeId.from("com.amazonaws.amplifyuibuilder#ListFormsLimit"),
32+
ShapeId.from("com.amazonaws.amplifyuibuilder#ListThemesLimit"),
33+
),
34+
ShapeId.from("com.amazonaws.drs#ElasticDisasterRecoveryService") to setOf(
35+
ShapeId.from("com.amazonaws.drs#Validity"),
36+
ShapeId.from("com.amazonaws.drs#CostOptimizationConfiguration\$burstBalanceThreshold"),
37+
ShapeId.from("com.amazonaws.drs#CostOptimizationConfiguration\$burstBalanceDeltaThreshold"),
38+
ShapeId.from("com.amazonaws.drs#ListStagingAccountsRequest\$maxResults"),
39+
ShapeId.from("com.amazonaws.drs#StrictlyPositiveInteger"),
40+
ShapeId.from("com.amazonaws.drs#MaxResultsType"),
41+
ShapeId.from("com.amazonaws.drs#MaxResultsReplicatingSourceServers"),
42+
ShapeId.from("com.amazonaws.drs#LaunchActionOrder"),
43+
),
44+
ShapeId.from("com.amazonaws.evidently#Evidently") to setOf(
45+
ShapeId.from("com.amazonaws.evidently#ResultsPeriod"),
46+
),
47+
ShapeId.from("com.amazonaws.location#LocationService") to setOf(
48+
ShapeId.from("com.amazonaws.location#ListPlaceIndexesRequest\$MaxResults"),
49+
ShapeId.from("com.amazonaws.location#SearchPlaceIndexForSuggestionsRequest\$MaxResults"),
50+
ShapeId.from("com.amazonaws.location#PlaceIndexSearchResultLimit"),
51+
),
52+
ShapeId.from("com.amazonaws.paymentcryptographydata#PaymentCryptographyDataPlane") to setOf(
53+
ShapeId.from("com.amazonaws.paymentcryptographydata#IntegerRangeBetween4And12"),
54+
),
55+
ShapeId.from("com.amazonaws.emrserverless#AwsToledoWebService") to setOf(
56+
ShapeId.from("com.amazonaws.emrserverless#WorkerCounts"),
57+
),
58+
)
59+
60+
override val order: Byte = 0
61+
62+
override fun enabledForService(model: Model, settings: KotlinSettings): Boolean =
63+
settings.service in removeDefaultsFrom
64+
65+
override fun preprocessModel(model: Model, settings: KotlinSettings): Model {
66+
val serviceId = settings.service
67+
val removeDefaultsFromShapes = removeDefaultsFrom[serviceId]
68+
?: throw CodegenException("expected $serviceId in removed defaults map")
69+
return removeDefaults(model, removeDefaultsFromShapes)
70+
}
71+
72+
fun removeDefaults(model: Model, fromShapes: Set<ShapeId>): Model {
73+
val removedRootDefaults: MutableSet<ShapeId> = HashSet()
74+
val removedRootDefaultsModel = ModelTransformer.create().mapShapes(model) {
75+
if (shouldRemoveRootDefault(it, fromShapes)) {
76+
removedRootDefaults.add(it.id)
77+
removeDefault(it)
78+
} else {
79+
it
80+
}
81+
}
82+
83+
return ModelTransformer.create().mapShapes(removedRootDefaultsModel) {
84+
if (shouldRemoveMemberDefault(it, removedRootDefaults, fromShapes)) {
85+
removeDefault(it)
86+
} else {
87+
it
88+
}
89+
}
90+
}
91+
92+
private fun shouldRemoveRootDefault(shape: Shape, removeDefaultsFrom: Set<ShapeId>): Boolean =
93+
shape !is MemberShape && shape.id in removeDefaultsFrom && shape.hasTrait<DefaultTrait>()
94+
95+
private fun shouldRemoveMemberDefault(
96+
shape: Shape,
97+
removedRootDefaults: Set<ShapeId>,
98+
removeDefaultsFrom: Set<ShapeId>,
99+
): Boolean = shape is MemberShape &&
100+
// Check the original set of shapes to remove for this shape id, to remove members that were in that set.
101+
(shape.target in removedRootDefaults || shape.id in removeDefaultsFrom) &&
102+
shape.hasTrait<DefaultTrait>()
103+
104+
private fun removeDefault(shape: Shape): Shape =
105+
((shape as ToSmithyBuilder<*>).toBuilder() as AbstractShapeBuilder<*, *>)
106+
.removeTrait(DefaultTrait.ID)
107+
.build()
108+
}

codegen/smithy-aws-kotlin-codegen/src/main/resources/META-INF/services/software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,4 @@ aws.sdk.kotlin.codegen.customization.machinelearning.MachineLearningEndpointCust
3232
aws.sdk.kotlin.codegen.customization.route53.TrimResourcePrefix
3333
aws.sdk.kotlin.codegen.customization.route53.ChangeResourceRecordSetsUnmarshallingIntegration
3434
aws.sdk.kotlin.codegen.customization.ec2.EC2MakePrimitivesOptional
35+
aws.sdk.kotlin.codegen.customization.RemoveDefaults
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package aws.sdk.kotlin.codegen.customization
7+
8+
import org.junit.jupiter.api.Test
9+
import software.amazon.smithy.kotlin.codegen.model.hasTrait
10+
import software.amazon.smithy.kotlin.codegen.test.toSmithyModel
11+
import software.amazon.smithy.model.shapes.ShapeId
12+
import software.amazon.smithy.model.traits.DefaultTrait
13+
import kotlin.test.assertFalse
14+
15+
class RemoveDefaultsTest {
16+
@Test
17+
fun removesDefaults() {
18+
val model = """
19+
${"$"}version: "2.0"
20+
21+
namespace test
22+
23+
structure Foo {
24+
bar: Bar = 0
25+
baz: Integer = 0
26+
}
27+
28+
@default(0)
29+
integer Bar
30+
31+
""".toSmithyModel()
32+
33+
val removeDefaultsFrom = setOf(ShapeId.from("test#Bar"), ShapeId.from("test#Foo\$baz"))
34+
val transformed = RemoveDefaults().removeDefaults(model, removeDefaultsFrom)
35+
val barMember = transformed.expectShape(ShapeId.from("test#Foo\$bar"))
36+
assertFalse(barMember.hasTrait<DefaultTrait>())
37+
val bazMember = transformed.expectShape(ShapeId.from("test#Foo\$baz"))
38+
assertFalse(bazMember.hasTrait<DefaultTrait>())
39+
val root = transformed.expectShape(ShapeId.from("test#Bar"))
40+
assertFalse(root.hasTrait<DefaultTrait>())
41+
}
42+
}

0 commit comments

Comments
 (0)