-
Notifications
You must be signed in to change notification settings - Fork 78
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add deprecated shape remover (#1511)
* Add deprecated shape remover & codegen tests for it. * ktlint * Update codegen test. * Update codegen test. --------- Co-authored-by: Sichan Yoo <chanyoo@amazon.com>
- Loading branch information
Showing
4 changed files
with
138 additions
and
0 deletions.
There are no files selected for viewing
37 changes: 37 additions & 0 deletions
37
...c/main/kotlin/software/amazon/smithy/aws/swift/codegen/model/AWSDeprecatedShapeRemover.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package software.amazon.smithy.aws.swift.codegen.model | ||
|
||
import software.amazon.smithy.model.Model | ||
import software.amazon.smithy.model.shapes.Shape | ||
import software.amazon.smithy.model.traits.DeprecatedTrait | ||
import software.amazon.smithy.model.transform.ModelTransformer | ||
import software.amazon.smithy.swift.codegen.SwiftSettings | ||
import software.amazon.smithy.swift.codegen.integration.SwiftIntegration | ||
import software.amazon.smithy.swift.codegen.model.getTrait | ||
import java.time.DateTimeException | ||
import java.time.LocalDate | ||
import java.time.format.DateTimeFormatter | ||
import java.util.function.Predicate | ||
|
||
private val DEPRECATED_SINCE_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd") | ||
|
||
private val REMOVE_BEFORE_DATE = "2024-09-17" | ||
|
||
/** | ||
* Parses a string of yyyy-MM-dd format to [LocalDate], returning `null` if parsing fails. | ||
*/ | ||
internal fun String.toLocalDate(): LocalDate? = try { LocalDate.parse(this, DEPRECATED_SINCE_DATE_FORMATTER) } catch (e: DateTimeException) { null } | ||
|
||
class AWSDeprecatedShapeRemover : SwiftIntegration { | ||
override fun preprocessModel(model: Model, settings: SwiftSettings): Model { | ||
return ModelTransformer.create().removeShapesIf( | ||
model, | ||
Predicate<Shape> { | ||
val since = it.getTrait<DeprecatedTrait>()?.since?.orElse(null) ?: return@Predicate false | ||
val deprecatedDate = since.toLocalDate() ?: return@Predicate false.also { | ||
println("Failed to parse `since` field $since as a date, skipping removal of deprecated shape $it") | ||
} | ||
return@Predicate deprecatedDate < REMOVE_BEFORE_DATE.toLocalDate() | ||
} | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
65 changes: 65 additions & 0 deletions
65
...t/kotlin/software/amazon/smithy/aws/swift/codegen/model/AWSDeprecatedShapeRemoverTests.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package software.amazon.smithy.aws.swift.codegen.model | ||
|
||
import io.kotest.matchers.string.shouldContainOnlyOnce | ||
import io.kotest.matchers.string.shouldNotContain | ||
import org.junit.jupiter.api.Test | ||
import software.amazon.smithy.aws.swift.codegen.TestContext | ||
import software.amazon.smithy.aws.swift.codegen.TestUtils | ||
import software.amazon.smithy.aws.swift.codegen.shouldSyntacticSanityCheck | ||
import software.amazon.smithy.aws.traits.protocols.RestJson1Trait | ||
|
||
class AWSDeprecatedShapeRemoverTests { | ||
@Test | ||
fun `Shape deprecated before the cutoff date based on deprecated trait's since field gets removed`() { | ||
val context = setupTests("deprecated-shape-removal-test.smithy", "com.test#Example") | ||
val contents = TestUtils.getModelFileContents("Example", "OperationWithDeprecatedInputMembersInput.swift", context.manifest) | ||
contents.shouldSyntacticSanityCheck() | ||
val removedContent = """ | ||
@available(*, deprecated, message: "API deprecated since 2024-09-01") | ||
public var deprecatedMemberWithCorrectlyFormedSinceField: Swift.String? | ||
""" | ||
contents.shouldNotContain(removedContent) | ||
} | ||
|
||
@Test | ||
fun `Shape deprecated after the cutoff date remains unremoved`() { | ||
val context = setupTests("deprecated-shape-removal-test.smithy", "com.test#Example") | ||
val contents = TestUtils.getModelFileContents("Example", "OperationWithDeprecatedInputMembersInput.swift", context.manifest) | ||
contents.shouldSyntacticSanityCheck() | ||
val expectedContents = """ | ||
@available(*, deprecated, message: "API deprecated since 2024-10-01") | ||
public var deprecatedMemberWithCorrectlyFormedSinceFieldButDeprecatedAfterCutoff: Swift.String? | ||
""" | ||
contents.shouldContainOnlyOnce(expectedContents) | ||
} | ||
|
||
@Test | ||
fun `Shape with deprecated trait that has malformed since field remains unremoved`() { | ||
val context = setupTests("deprecated-shape-removal-test.smithy", "com.test#Example") | ||
val contents = TestUtils.getModelFileContents("Example", "OperationWithDeprecatedInputMembersInput.swift", context.manifest) | ||
contents.shouldSyntacticSanityCheck() | ||
val expectedContents = """ | ||
@available(*, deprecated, message: "API deprecated since 4.2.0") | ||
public var deprecatedMemberWithMalformedSinceField: Swift.String? | ||
""" | ||
contents.shouldContainOnlyOnce(expectedContents) | ||
} | ||
|
||
@Test | ||
fun `Shape with deprecated trait missing since field remains unremoved`() { | ||
val context = setupTests("deprecated-shape-removal-test.smithy", "com.test#Example") | ||
val contents = TestUtils.getModelFileContents("Example", "OperationWithDeprecatedInputMembersInput.swift", context.manifest) | ||
contents.shouldSyntacticSanityCheck() | ||
val expectedContents = """ | ||
@available(*, deprecated) | ||
public var deprecatedMemberWithoutSinceField: Swift.String? | ||
""" | ||
contents.shouldContainOnlyOnce(expectedContents) | ||
} | ||
|
||
private fun setupTests(smithyFile: String, serviceShapeId: String): TestContext { | ||
val context = TestUtils.executeDirectedCodegen(smithyFile, serviceShapeId, RestJson1Trait.ID) | ||
context.ctx.delegator.flushWriters() | ||
return context | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
...t/resources/software.amazon.smithy.aws.swift.codegen/deprecated-shape-removal-test.smithy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
$version: "2.0" | ||
namespace com.test | ||
|
||
use aws.api#service | ||
use aws.protocols#restJson1 | ||
use aws.auth#sigv4 | ||
|
||
@service(sdkId: "Example") | ||
@restJson1 | ||
@sigv4(name: "Example") | ||
service Example { | ||
version: "1.0.0", | ||
operations: [ | ||
OperationWithDeprecatedInputMembers | ||
] | ||
} | ||
|
||
@http(method: "POST", uri: "/foo") | ||
operation OperationWithDeprecatedInputMembers { | ||
input: InputWithDeprecatedMembers | ||
} | ||
|
||
structure InputWithDeprecatedMembers { | ||
@deprecated(since: "2024-09-01") | ||
deprecatedMemberWithCorrectlyFormedSinceField: String | ||
|
||
@deprecated(since: "2024-10-01") | ||
deprecatedMemberWithCorrectlyFormedSinceFieldButDeprecatedAfterCutoff: String | ||
|
||
@deprecated(since: "4.2.0") | ||
deprecatedMemberWithMalformedSinceField: String | ||
|
||
@deprecated | ||
deprecatedMemberWithoutSinceField: String | ||
} |