Skip to content

Commit 153f02f

Browse files
authored
refactor: migrate non AWS specific protocol generation (#1012)
**refactor**: remove unused `KotlinIntegration::onShapeWriterUse` extension function **refactor**: Replace `KotlinIntegration::renderBindEndpointBuiltins` with a new function `customizeEndpointResolution` which allows for more than just overriding rendering support for builtins. It allows registering custom property renderers and custom function support. **refactor**: Remove exception base class from `ProtocolGenerator` in favor of declaring a section that can be overwritten. The logic for rendering the exception has been abstracted to `ServiceExceptionBaseClassGenerator` so that it can mostly be re-used when doing so. **refactor**: Migrate `mergeSequential` from `aws-sdk-kotlin` runtime to `smithy-kotlin` runtime. There wasn't anything AWS specific about this and it is only used for event streams (currently) **refactor**: Sigv4 integration * Move various bits of codegen into section writers (support for protocol test service client setup) * Migrate logic from the AWS endpoint delegator into the new `EndpointCustomization` type **refactor**: Move support for the `SDK::Endpoint` builtin into a `KotlinIntegration` **refactor**: Move generation of `mergeServiceDefaults` into `HttpProtocolClientGenerator`. The function was never AWS specific, it just sets default operation execution context attributes. **refactor**: Always generate an override of the operation `retryPolicy` in `HttpProtocolClientGenerator` since it is always registered as a service client configuration property. **refactor**: Move the Smithy build transforms from `aws-sdk-kotlin` since they aren't specific to the SDK. Code/tests did not change, just the name of the transform.
1 parent 8cd8a95 commit 153f02f

File tree

35 files changed

+859
-216
lines changed

35 files changed

+859
-216
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"id": "85c1a6d6-9e18-475a-8c8a-766d041530ab",
3+
"type": "misc",
4+
"description": "Refactor codegen to move non AWS specific support into core"
5+
}

codegen/smithy-kotlin-codegen-testutils/src/main/kotlin/software/amazon/smithy/kotlin/codegen/test/ModelTestUtils.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ fun Model.newTestContext(
122122
val manifest = MockManifest()
123123
val provider: SymbolProvider = KotlinCodegenPlugin.createSymbolProvider(model = this, rootNamespace = packageName, serviceName = serviceName, settings = settings)
124124
val service = this.getShape(ShapeId.from("$packageName#$serviceName")).get().asServiceShape().get()
125-
val delegator = KotlinDelegator(settings, this, manifest, provider)
125+
val delegator = KotlinDelegator(settings, this, manifest, provider, integrations)
126126

127127
val ctx = ProtocolGenerator.GenerationContext(
128128
settings,

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/core/KotlinDelegator.kt

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -111,17 +111,6 @@ class KotlinDelegator(
111111
writer.addImportReferences(symbol, SymbolReference.ContextOption.DECLARE)
112112
writer.dependencies.addAll(symbol.dependencies)
113113
writer.pushState()
114-
115-
// shape is stored in the property bag when generated, if it's there pull it back out
116-
val shape = symbol.getProperty("shape", Shape::class.java)
117-
if (shape.isPresent) {
118-
// Allow integrations to do things like add onSection callbacks.
119-
// these onSection callbacks are removed when popState is called.
120-
for (integration in integrations) {
121-
integration.onShapeWriterUse(settings, model, symbolProvider, writer, shape.get())
122-
}
123-
}
124-
125114
block(writer)
126115
writer.popState()
127116
}

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/core/RuntimeTypes.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ object RuntimeTypes {
171171
val flattenIfPossible = symbol("flattenIfPossible")
172172
val LazyAsyncValue = symbol("LazyAsyncValue")
173173
val length = symbol("length")
174+
val mergeSequential = symbol("mergeSequential")
174175
val truthiness = symbol("truthiness")
175176
val toNumber = symbol("toNumber")
176177
val type = symbol("type")

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/integration/KotlinIntegration.kt

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,12 @@ import software.amazon.smithy.codegen.core.SymbolProvider
88
import software.amazon.smithy.kotlin.codegen.*
99
import software.amazon.smithy.kotlin.codegen.core.CodegenContext
1010
import software.amazon.smithy.kotlin.codegen.core.KotlinDelegator
11-
import software.amazon.smithy.kotlin.codegen.core.KotlinWriter
11+
import software.amazon.smithy.kotlin.codegen.rendering.endpoints.EndpointCustomization
1212
import software.amazon.smithy.kotlin.codegen.rendering.protocol.ProtocolGenerator
1313
import software.amazon.smithy.kotlin.codegen.rendering.protocol.ProtocolMiddleware
1414
import software.amazon.smithy.kotlin.codegen.rendering.util.ConfigProperty
1515
import software.amazon.smithy.model.Model
1616
import software.amazon.smithy.model.shapes.ServiceShape
17-
import software.amazon.smithy.model.shapes.Shape
18-
import software.amazon.smithy.rulesengine.language.EndpointRuleSet
1917

2018
/**
2119
* JVM SPI for customizing Kotlin code generation, registering new protocol
@@ -97,30 +95,6 @@ interface KotlinIntegration {
9795
symbolProvider: SymbolProvider,
9896
): SymbolProvider = symbolProvider
9997

100-
/**
101-
* Called each time a writer is used that defines a shape.
102-
*
103-
* Any mutations made on the writer (for example, adding
104-
* section interceptors) are removed after the callback has completed;
105-
* the callback is invoked in between pushing and popping state from
106-
* the writer.
107-
*
108-
* @param settings Settings used to generate.
109-
* @param model Model to generate from.
110-
* @param symbolProvider Symbol provider used for codegen.
111-
* @param writer Writer that will be used.
112-
* @param definedShape Shape that is being defined in the writer.
113-
*/
114-
fun onShapeWriterUse(
115-
settings: KotlinSettings,
116-
model: Model,
117-
symbolProvider: SymbolProvider,
118-
writer: KotlinWriter,
119-
definedShape: Shape,
120-
) {
121-
// pass
122-
}
123-
12498
/**
12599
* Write additional files defined by this integration
126100
* @param ctx The codegen generation context
@@ -154,10 +128,8 @@ interface KotlinIntegration {
154128
fun authSchemes(ctx: ProtocolGenerator.GenerationContext): List<AuthSchemeHandler> = emptyList()
155129

156130
/**
157-
* Render binding of endpoint ruleset builtin parameters
158-
* @param ctx The codegen generation context
159-
* @param rules The endpoint rules
160-
* @param writer The writer to render to
131+
* Register an endpoint customization
132+
* @param ctx the codegen generation context
161133
*/
162-
fun renderBindEndpointBuiltins(ctx: ProtocolGenerator.GenerationContext, rules: EndpointRuleSet, writer: KotlinWriter) {}
134+
fun customizeEndpointResolution(ctx: ProtocolGenerator.GenerationContext): EndpointCustomization? = null
163135
}

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/rendering/ExceptionBaseClassGenerator.kt

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,57 @@ import software.amazon.smithy.codegen.core.Symbol
1010
import software.amazon.smithy.kotlin.codegen.KotlinSettings
1111
import software.amazon.smithy.kotlin.codegen.core.*
1212
import software.amazon.smithy.kotlin.codegen.integration.SectionId
13+
import software.amazon.smithy.kotlin.codegen.integration.SectionKey
1314
import software.amazon.smithy.kotlin.codegen.model.buildSymbol
14-
import software.amazon.smithy.kotlin.codegen.rendering.protocol.ProtocolGenerator
15+
import software.amazon.smithy.kotlin.codegen.model.namespace
1516
import software.amazon.smithy.model.knowledge.TopDownIndex
1617

1718
/**
1819
* Renders the base class that all (modeled) exceptions inherit from.
1920
* Protocol generators are allowed to override this but they MUST inherit from the base `ServiceException`
2021
* with the expected constructors.
22+
*
2123
*/
2224
object ExceptionBaseClassGenerator {
2325

26+
val DefaultServiceExceptionSymbol: Symbol = buildSymbol {
27+
name = "ServiceException"
28+
namespace(KotlinDependency.CORE)
29+
}
30+
2431
/**
2532
* Defines a section in which code can be added to the body of the base exception type.
2633
*/
27-
object ExceptionBaseClassSection : SectionId
34+
object ExceptionBaseClassSection : SectionId {
35+
val CodegenContext: SectionKey<CodegenContext> = SectionKey("CodegenContext")
36+
}
37+
38+
fun render(ctx: CodegenContext, writer: KotlinWriter) {
39+
writer.declareSection(ExceptionBaseClassSection, mapOf(ExceptionBaseClassSection.CodegenContext to ctx)) {
40+
ServiceExceptionBaseClassGenerator().render(ctx, writer)
41+
}
42+
}
43+
44+
/**
45+
* Get the (generated) symbol that constitutes the base class exceptions will inherit from
46+
*/
47+
fun baseExceptionSymbol(settings: KotlinSettings): Symbol = buildSymbol {
48+
val serviceName = clientName(settings.sdkId)
49+
name = "${serviceName}Exception"
50+
namespace = "${settings.pkg.name}.model"
51+
definitionFile = "$name.kt"
52+
}
53+
}
2854

55+
/**
56+
* Re-usable component for generating the base exception that all generated error shapes will inherit from.
57+
* @param parent symbol to inherit from (defaults to [ExceptionBaseClassGenerator.DefaultServiceExceptionSymbol])
58+
*/
59+
open class ServiceExceptionBaseClassGenerator(
60+
private val parent: Symbol = ExceptionBaseClassGenerator.DefaultServiceExceptionSymbol,
61+
) {
2962
fun render(ctx: CodegenContext, writer: KotlinWriter) {
30-
val baseException = ctx.protocolGenerator?.exceptionBaseClassSymbol ?: ProtocolGenerator.DefaultServiceExceptionSymbol
31-
writer.addImport(baseException)
32-
val serviceException = baseExceptionSymbol(ctx.settings).also { checkForCollision(ctx, it) }
63+
val serviceException = ExceptionBaseClassGenerator.baseExceptionSymbol(ctx.settings).also { checkForCollision(ctx, it) }
3364

3465
val name = clientName(ctx.settings.sdkId)
3566
writer.dokka("Base class for all service related exceptions thrown by the $name client")
@@ -38,26 +69,20 @@ object ExceptionBaseClassGenerator {
3869
"}",
3970
ctx.settings.api.visibility,
4071
serviceException,
41-
baseException,
72+
parent,
4273
) {
4374
write("public constructor() : super()")
4475
write("public constructor(message: String?) : super(message)")
4576
write("public constructor(message: String?, cause: Throwable?) : super(message, cause)")
4677
write("public constructor(cause: Throwable?) : super(cause)")
47-
48-
writer.declareSection(ExceptionBaseClassSection)
78+
renderExtra(ctx, writer)
4979
}
5080
}
5181

5282
/**
53-
* Get the (generated) symbol that constitutes the base class exceptions will inherit from
83+
* Hook for subclasses to render additional overrides or methods on the base exception
5484
*/
55-
fun baseExceptionSymbol(settings: KotlinSettings): Symbol = buildSymbol {
56-
val serviceName = clientName(settings.sdkId)
57-
name = "${serviceName}Exception"
58-
namespace = "${settings.pkg.name}.model"
59-
definitionFile = "$name.kt"
60-
}
85+
protected open fun renderExtra(ctx: CodegenContext, writer: KotlinWriter) { }
6186

6287
// Compare generated base exception name with all error type names. Throw exception if not unique.
6388
private fun checkForCollision(ctx: CodegenContext, exceptionSymbol: Symbol) {

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/rendering/ServiceClientGenerator.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class ServiceClientGenerator(private val ctx: RenderingContext<ServiceShape>) {
7777
writer.write("\n\n")
7878
writer.write("#L const val ServiceId: String = #S", ctx.settings.api.visibility, ctx.settings.sdkId)
7979
writer.write("#L const val SdkVersion: String = #S", ctx.settings.api.visibility, ctx.settings.pkg.version)
80+
writer.write("#L const val ServiceApiVersion: String = #S", ctx.settings.api.visibility, service.version)
8081
writer.write("\n\n")
8182

8283
writer.putContext("service.name", ctx.settings.sdkId)

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/rendering/auth/BearerTokenAuthSchemeIntegration.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@ import software.amazon.smithy.kotlin.codegen.KotlinSettings
1111
import software.amazon.smithy.kotlin.codegen.core.CodegenContext
1212
import software.amazon.smithy.kotlin.codegen.core.KotlinWriter
1313
import software.amazon.smithy.kotlin.codegen.core.RuntimeTypes
14+
import software.amazon.smithy.kotlin.codegen.core.getContextValue
15+
import software.amazon.smithy.kotlin.codegen.integration.AppendingSectionWriter
1416
import software.amazon.smithy.kotlin.codegen.integration.AuthSchemeHandler
1517
import software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration
18+
import software.amazon.smithy.kotlin.codegen.integration.SectionWriterBinding
1619
import software.amazon.smithy.kotlin.codegen.model.buildSymbol
20+
import software.amazon.smithy.kotlin.codegen.rendering.protocol.HttpProtocolClientGenerator
1721
import software.amazon.smithy.kotlin.codegen.rendering.protocol.ProtocolGenerator
1822
import software.amazon.smithy.kotlin.codegen.rendering.util.ConfigProperty
1923
import software.amazon.smithy.kotlin.codegen.rendering.util.ConfigPropertyType
@@ -54,6 +58,22 @@ class BearerTokenAuthSchemeIntegration : KotlinIntegration {
5458

5559
return listOf(bearerTokenProviderProp)
5660
}
61+
62+
override val sectionWriters: List<SectionWriterBinding>
63+
get() = listOf(
64+
SectionWriterBinding(HttpProtocolClientGenerator.ClientInitializer, renderClientInitializer),
65+
)
66+
67+
private val renderClientInitializer = AppendingSectionWriter { writer ->
68+
val ctx = writer.getContextValue(HttpProtocolClientGenerator.ClientInitializer.GenerationContext)
69+
val serviceIndex = ServiceIndex.of(ctx.model)
70+
val hasBearerTokenAuth = serviceIndex
71+
.getAuthSchemes(ctx.settings.service)
72+
.containsKey(HttpBearerAuthTrait.ID)
73+
if (hasBearerTokenAuth) {
74+
writer.write("managedResources.#T(config.bearerTokenProvider)", RuntimeTypes.Core.IO.addIfManaged)
75+
}
76+
}
5777
}
5878

5979
class BearerTokenAuthSchemeHandler : AuthSchemeHandler {

0 commit comments

Comments
 (0)