Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Selectively generate read & write methods for structs & unions #721

Merged
merged 63 commits into from
May 10, 2024

Conversation

jbelkins
Copy link
Contributor

Issue #

awslabs/aws-sdk-swift#1495

Description of changes

Only code-generate read / write methods for structures & unions that are actually used by AWS operations.

  • Search the Smithy model and tag those structs & unions that are read from or written to with a custom trait.
  • When code-generating read & write methods, only generate methods for structs or unions that have the appropriate traits.

This saves ~100,000 lines of dead code across all AWS service clients.

Scope

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@@ -55,6 +56,7 @@ class SwiftCodegenPlugin : SmithyBuildPlugin {
resolvedModel = NestedShapeTransformer.transform(resolvedModel, settings.getService(resolvedModel))
resolvedModel = UnionIndirectivizer.transform(resolvedModel)
resolvedModel = EquatableConformanceTransformer.transform(resolvedModel, settings.getService(resolvedModel))
resolvedModel = NeedsReaderWriterTransformer.transform(resolvedModel, settings.getService(resolvedModel))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adds a new model transformer before codegen.

import software.amazon.smithy.model.shapes.ShapeId
import software.amazon.smithy.model.traits.Trait

class NeedsReaderTrait : Trait {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A simple custom trait we can use to mark the struct or union shapes that need to have a reader code-generated for them.

import software.amazon.smithy.model.shapes.ShapeId
import software.amazon.smithy.model.traits.Trait

class NeedsWriterTrait : Trait {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A simple custom trait we can use to mark the struct or union shapes that need to have a writer code-generated for them.

@@ -220,17 +223,40 @@ abstract class HTTPBindingProtocolGenerator(
// get all members sorted by name and filter out either all members with other traits OR members with the payload trait
val httpBodyMembers = members.filter { it.isInHttpBody() }
val path = "properties.".takeIf { shape.hasTrait<ErrorTrait>() } ?: ""
writer.write("")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check if the NeedsWriter trait is present before generating a writer, and that the NeedsReader trait is present before generating a reader.

(code looks substantially different because it was reformatted but the method calls are identical.)

return modelToReturn
}

private fun transform(model: Model, structure: StructureShape, trait: Trait): Model {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is used recursively to traverse the model tree and add the trait (either NeedsReader or NeedsWriter) to structs and unions that descend from either an input (for NeedsWriter) or an output (for NeedsReader.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shapes that already have the trait are excluded from the transformation to prevent endless loops when shapes have self-references.

@@ -135,6 +135,24 @@ fun Model.getNestedShapes(shape: Shape): Set<Shape> {
.select(this)
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These model selectors are used to extract the needed subset of shapes from the model for use above.

@@ -144,13 +144,6 @@ extension RestJsonProtocolClientTypes.RenamedGreeting {
guard let value else { return }
try writer["salutation"].write(value.salutation)
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and following are test files, the NeedsReaderWriterTransformer has to be applied to the text contexts, and some test expectations no longer have both a reader & writer.

@jbelkins jbelkins marked this pull request as ready for review May 10, 2024 04:16
@jbelkins jbelkins merged commit 1fbe84e into main May 10, 2024
17 checks passed
@jbelkins jbelkins deleted the jbe/selective_read_write_closures branch May 10, 2024 16:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants