Skip to content

Commit 910b613

Browse files
authored
chore: enable explicit API mode for codegen (#675)
1 parent dd889b9 commit 910b613

24 files changed

+267
-242
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"id": "4d59fd7e-dde7-4816-8485-cc3140a41512",
3+
"type": "misc",
4+
"description": "Enable [Explicit API mode](https://github.com/Kotlin/KEEP/blob/master/proposals/explicit-api-mode.md)"
5+
}

smithy-kotlin-codegen/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ tasks.test {
9090
testLogging {
9191
events("passed", "skipped", "failed")
9292
showStandardStreams = true
93+
showStackTraces = true
94+
showExceptions = true
95+
exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
9396
}
9497
}
9598

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

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ class ClientConfigGenerator(
7575
.joinToString(", ")
7676

7777
val formattedBaseClasses = if (baseClasses.isNotEmpty()) ": $baseClasses" else ""
78-
ctx.writer.openBlock("class #configClass.name:L private constructor(builder: Builder)$formattedBaseClasses {")
78+
ctx.writer.openBlock("public class #configClass.name:L private constructor(builder: Builder)$formattedBaseClasses {")
7979
.call { renderImmutableProperties() }
8080
.call { renderCompanionObject() }
8181
.call { renderBuilder() }
@@ -85,14 +85,14 @@ class ClientConfigGenerator(
8585
}
8686

8787
private fun renderCompanionObject() {
88-
ctx.writer.withBlock("companion object {", "}") {
88+
ctx.writer.withBlock("public companion object {", "}") {
8989
if (builderReturnType != null) {
9090
write(
91-
"inline operator fun invoke(block: Builder.() -> kotlin.Unit): #T = Builder().apply(block).build()",
91+
"public inline operator fun invoke(block: Builder.() -> kotlin.Unit): #T = Builder().apply(block).build()",
9292
builderReturnType
9393
)
9494
} else {
95-
write("inline operator fun invoke(block: Builder.() -> kotlin.Unit): #configClass.name:L = Builder().apply(block).build()")
95+
write("public inline operator fun invoke(block: Builder.() -> kotlin.Unit): #configClass.name:L = Builder().apply(block).build()")
9696
}
9797
}
9898
}
@@ -115,26 +115,26 @@ class ClientConfigGenerator(
115115

116116
private fun renderImmutableProperties() {
117117
props.forEach { prop ->
118-
val override = if (prop.requiresOverride) "override " else ""
118+
val override = if (prop.requiresOverride) "override" else "public"
119119

120120
when (prop.propertyType) {
121121
is ClientConfigPropertyType.SymbolDefault -> {
122-
ctx.writer.write("${override}val #1L: #2P = builder.#1L", prop.propertyName, prop.symbol)
122+
ctx.writer.write("$override val #1L: #2P = builder.#1L", prop.propertyName, prop.symbol)
123123
}
124124
is ClientConfigPropertyType.ConstantValue -> {
125-
ctx.writer.write("${override}val #1L: #2T = #3L", prop.propertyName, prop.symbol, prop.propertyType.value)
125+
ctx.writer.write("$override val #1L: #2T = #3L", prop.propertyName, prop.symbol, prop.propertyType.value)
126126
}
127127
is ClientConfigPropertyType.Required -> {
128128
ctx.writer.write(
129-
"${override}val #1L: #2T = requireNotNull(builder.#1L) { #3S }",
129+
"$override val #1L: #2T = requireNotNull(builder.#1L) { #3S }",
130130
prop.propertyName,
131131
prop.symbol,
132132
prop.propertyType.message ?: "${prop.propertyName} is a required configuration property"
133133
)
134134
}
135135
is ClientConfigPropertyType.RequiredWithDefault -> {
136136
ctx.writer.write(
137-
"${override}val #1L: #2T = builder.#1L ?: #3L",
137+
"$override val #1L: #2T = builder.#1L ?: #3L",
138138
prop.propertyName,
139139
prop.symbol,
140140
prop.propertyType.default
@@ -147,13 +147,13 @@ class ClientConfigGenerator(
147147

148148
private fun renderBuilder() {
149149
ctx.writer.write("")
150-
.withBlock("class Builder {", "}") {
150+
.withBlock("public class Builder {", "}") {
151151
// override DSL properties
152152
props
153153
.filter { it.propertyType !is ClientConfigPropertyType.ConstantValue }
154154
.forEach { prop ->
155155
prop.documentation?.let { ctx.writer.dokka(it) }
156-
write("var #L: #D", prop.propertyName, prop.symbol)
156+
write("public var #L: #D", prop.propertyName, prop.symbol)
157157
}
158158
write("")
159159

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ class EnumGenerator(val shape: StringShape, val symbol: Symbol, val writer: Kotl
109109
writer.renderDocumentation(shape)
110110
writer.renderAnnotations(shape)
111111
// NOTE: The smithy spec only allows string shapes to apply to a string shape at the moment
112-
writer.withBlock("sealed class ${symbol.name} {", "}") {
113-
write("\nabstract val value: #Q\n", KotlinTypes.String)
112+
writer.withBlock("public sealed class ${symbol.name} {", "}") {
113+
write("\npublic abstract val value: #Q\n", KotlinTypes.String)
114114

115115
val sortedDefinitions = enumTrait
116116
.values
@@ -124,16 +124,16 @@ class EnumGenerator(val shape: StringShape, val symbol: Symbol, val writer: Kotl
124124
if (generatedNames.contains("SdkUnknown")) throw CodegenException("generating SdkUnknown would cause duplicate variant for enum shape: $shape")
125125

126126
// generate the unknown which will always be last
127-
writer.withBlock("data class SdkUnknown(override val value: #Q) : #Q() {", "}", KotlinTypes.String, symbol) {
127+
writer.withBlock("public data class SdkUnknown(override val value: #Q) : #Q() {", "}", KotlinTypes.String, symbol) {
128128
renderToStringOverride()
129129
}
130130

131131
write("")
132132

133133
// generate the fromValue() static method
134-
withBlock("companion object {", "}") {
134+
withBlock("public companion object {", "}") {
135135
writer.dokka("Convert a raw value to one of the sealed variants or [SdkUnknown]")
136-
openBlock("fun fromValue(str: #Q): #Q = when(str) {", KotlinTypes.String, symbol)
136+
openBlock("public fun fromValue(str: #Q): #Q = when(str) {", KotlinTypes.String, symbol)
137137
.call {
138138
sortedDefinitions.forEach { definition ->
139139
val variantName = getVariantName(definition)
@@ -145,7 +145,7 @@ class EnumGenerator(val shape: StringShape, val symbol: Symbol, val writer: Kotl
145145
.write("")
146146

147147
writer.dokka("Get a list of all possible variants")
148-
openBlock("fun values(): #Q<#Q> = listOf(", KotlinTypes.Collections.List, symbol)
148+
openBlock("public fun values(): #Q<#Q> = listOf(", KotlinTypes.Collections.List, symbol)
149149
.call {
150150
sortedDefinitions.forEachIndexed { idx, definition ->
151151
val variantName = getVariantName(definition)
@@ -170,7 +170,7 @@ class EnumGenerator(val shape: StringShape, val symbol: Symbol, val writer: Kotl
170170
throw CodegenException("prefixing invalid enum value to form a valid Kotlin identifier causes generated sealed class names to not be unique: $variantName; shape=$shape")
171171
}
172172

173-
writer.openBlock("object $variantName : #Q() {", symbol)
173+
writer.openBlock("public object $variantName : #Q() {", symbol)
174174
.write("override val value: #Q = #S", KotlinTypes.String, definition.value)
175175
.call { renderToStringOverride() }
176176
.closeBlock("}")

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,14 @@ object ExceptionBaseClassGenerator {
3434
val name = clientName(ctx.settings.sdkId)
3535
writer.dokka("Base class for all service related exceptions thrown by the $name client")
3636
writer.withBlock(
37-
"open class #T : #T {", "}",
37+
"public open class #T : #T {", "}",
3838
serviceException,
3939
baseException
4040
) {
41-
write("constructor() : super()")
42-
write("constructor(message: String?) : super(message)")
43-
write("constructor(message: String?, cause: Throwable?) : super(message, cause)")
44-
write("constructor(cause: Throwable?) : super(cause)")
41+
write("public constructor() : super()")
42+
write("public constructor(message: String?) : super(message)")
43+
write("public constructor(message: String?, cause: Throwable?) : super(message, cause)")
44+
write("public constructor(cause: Throwable?) : super(cause)")
4545

4646
writer.declareSection(ExceptionBaseClassSection)
4747
}

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ fun renderKmpGradleBuild(
9797
#W
9898
9999
kotlin {
100+
#W
100101
#W
101102
sourceSets {
102103
val commonMain by getting {
@@ -119,6 +120,7 @@ fun renderKmpGradleBuild(
119120
}
120121
""".trimIndent(),
121122
pluginsRenderer,
123+
{ w: GradleWriter -> if (isRootModule) w.write("explicitApi()") },
122124
{ w: GradleWriter -> if (isRootModule) repositoryRenderer(w) },
123125
{ w: GradleWriter -> if (isRootModule) renderRootJvmPluginConfig(w) else w.write("jvm()") },
124126
{ w: GradleWriter -> renderDependencies(w, scope = Scope.SOURCE, isKmp = true, dependencies = dependencies) },
@@ -168,8 +170,11 @@ fun renderJvmGradleBuild(
168170
val optInAnnotations = listOf(
169171
#W
170172
)
171-
kotlin.sourceSets.all {
172-
optInAnnotations.forEach { languageSettings.optIn(it) }
173+
kotlin {
174+
#W
175+
sourceSets.all {
176+
optInAnnotations.forEach { languageSettings.optIn(it) }
177+
}
173178
}
174179
175180
tasks.test {
@@ -183,7 +188,8 @@ fun renderJvmGradleBuild(
183188
pluginsRenderer,
184189
{ w: GradleWriter -> if (isRootModule) repositoryRenderer(w) },
185190
{ w: GradleWriter -> renderDependencies(w, scope = Scope.SOURCE, isKmp = false, dependencies = dependencies) },
186-
annotationRenderer
191+
annotationRenderer,
192+
{ w: GradleWriter -> if (isRootModule) w.write("explicitApi()") },
187193
)
188194
}
189195

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ class PaginatorGenerator : KotlinIntegration {
131131
)
132132
.addImportReferences(cursorSymbol, SymbolReference.ContextOption.DECLARE)
133133
.withBlock(
134-
"fun #T.#LPaginated(initialRequest: #T): #T<#T> =",
134+
"public fun #T.#LPaginated(initialRequest: #T): #T<#T> =",
135135
"",
136136
serviceSymbol,
137137
operationShape.defaultName(),
@@ -168,7 +168,7 @@ class PaginatorGenerator : KotlinIntegration {
168168
""".trimMargin()
169169
)
170170
.withBlock(
171-
"fun #T.#LPaginated(block: #T.Builder.() -> #T): #T<#T> =",
171+
"public fun #T.#LPaginated(block: #T.Builder.() -> #T): #T<#T> =",
172172
"",
173173
serviceSymbol,
174174
operationShape.defaultName(),
@@ -211,7 +211,7 @@ class PaginatorGenerator : KotlinIntegration {
211211
itemDesc.targetMember.defaultName(serviceShape)
212212
)
213213
.withBlock(
214-
"fun #T<#T>.#L(): #T<#L> =", "",
214+
"public fun #T<#T>.#L(): #T<#L> =", "",
215215
ExternalTypes.KotlinxCoroutines.Flow,
216216
outputSymbol,
217217
itemDesc.itemLiteral,

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

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,12 @@ class ServiceGenerator(private val ctx: RenderingContext<ServiceShape>) {
6060

6161
writer.renderDocumentation(service)
6262
writer.renderAnnotations(service)
63-
writer.openBlock("interface ${serviceSymbol.name} : SdkClient {")
63+
writer.openBlock("public interface ${serviceSymbol.name} : SdkClient {")
6464
.call { overrideServiceName() }
6565
.call {
6666
// allow access to client's Config
6767
writer.dokka("${serviceSymbol.name}'s configuration")
68-
writer.write("val config: Config")
68+
writer.write("public val config: Config")
6969
}
7070
.call {
7171
// allow integrations to add additional fields to companion object or configuration
@@ -113,16 +113,16 @@ class ServiceGenerator(private val ctx: RenderingContext<ServiceShape>) {
113113
* ```
114114
*/
115115
private fun renderCompanionObject() {
116-
writer.withBlock("companion object {", "}") {
116+
writer.withBlock("public companion object {", "}") {
117117
val hasProtocolGenerator = ctx.protocolGenerator != null
118118
// If there is no ProtocolGenerator, do not codegen references to the non-existent default client.
119119
callIf(hasProtocolGenerator) {
120-
withBlock("operator fun invoke(block: Config.Builder.() -> Unit = {}): ${serviceSymbol.name} {", "}") {
120+
withBlock("public operator fun invoke(block: Config.Builder.() -> Unit = {}): ${serviceSymbol.name} {", "}") {
121121
write("val config = Config.Builder().apply(block).build()")
122122
write("return Default${serviceSymbol.name}(config)")
123123
}
124124
write("")
125-
write("operator fun invoke(config: Config): ${serviceSymbol.name} = Default${serviceSymbol.name}(config)")
125+
write("public operator fun invoke(config: Config): ${serviceSymbol.name} = Default${serviceSymbol.name}(config)")
126126
}
127127
}
128128
}
@@ -153,25 +153,35 @@ class ServiceGenerator(private val ctx: RenderingContext<ServiceShape>) {
153153
writer.write("")
154154
writer.renderDocumentation(op)
155155
writer.renderAnnotations(op)
156-
writer.write(opIndex.operationSignature(ctx.model, ctx.symbolProvider, op, includeOptionalDefault = true))
156+
157+
val signature = opIndex.operationSignature(ctx.model, ctx.symbolProvider, op, includeOptionalDefault = true)
158+
writer.write("public #L", signature)
157159
}
158160

159161
private fun renderOperationDslOverload(opIndex: OperationIndex, op: OperationShape) {
160162
// Add DSL overload (if appropriate)
161163
opIndex.getInput(op).ifPresent { inputShape ->
162-
val outputShape = opIndex.getOutput(op)
163-
val hasOutputStream = outputShape.map { it.hasStreamingMember(ctx.model) }.orElse(false)
164-
165-
if (!hasOutputStream) {
166-
val input = ctx.symbolProvider.toSymbol(inputShape).name
167-
val operationName = op.defaultName()
168-
169-
writer.write("")
170-
writer.renderDocumentation(op)
171-
writer.renderAnnotations(op)
172-
val signature = "suspend inline fun ${serviceSymbol.name}.$operationName(crossinline block: $input.Builder.() -> Unit)"
173-
val impl = "$operationName($input.Builder().apply(block).build())"
174-
writer.write("$signature = $impl")
164+
opIndex.getOutput(op).ifPresent { outputShape ->
165+
val hasOutputStream = outputShape.hasStreamingMember(ctx.model)
166+
167+
if (!hasOutputStream) {
168+
val inputSymbol = ctx.symbolProvider.toSymbol(inputShape)
169+
val outputSymbol = ctx.symbolProvider.toSymbol(outputShape)
170+
val operationName = op.defaultName()
171+
172+
writer.write("")
173+
writer.renderDocumentation(op)
174+
writer.renderAnnotations(op)
175+
writer.write(
176+
"public suspend inline fun #T.#L(crossinline block: #T.Builder.() -> Unit): #T = #L(#T.Builder().apply(block).build())",
177+
serviceSymbol,
178+
operationName,
179+
inputSymbol,
180+
outputSymbol,
181+
operationName,
182+
inputSymbol,
183+
)
184+
}
175185
}
176186
}
177187
}

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

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class StructureGenerator(
5151
* Renders a normal (non-error) Smithy structure to a Kotlin class
5252
*/
5353
private fun renderStructure() {
54-
writer.openBlock("class #T private constructor(builder: Builder) {", symbol)
54+
writer.openBlock("public class #T private constructor(builder: Builder) {", symbol)
5555
.call { renderImmutableProperties() }
5656
.write("")
5757
.call { renderCompanionObject() }
@@ -87,18 +87,18 @@ class StructureGenerator(
8787

8888
memberShape.hasTrait<HttpLabelTrait>() ->
8989
writer.write(
90-
"""val #1L: #2F = requireNotNull(builder.#1L) { "A non-null value must be provided for #1L" }""",
90+
"""public val #1L: #2F = requireNotNull(builder.#1L) { "A non-null value must be provided for #1L" }""",
9191
memberName,
9292
memberSymbol,
9393
)
9494

95-
else -> writer.write("val #1L: #2F = builder.#1L", memberName, memberSymbol)
95+
else -> writer.write("public val #1L: #2F = builder.#1L", memberName, memberSymbol)
9696
}
9797
}
9898

9999
private fun renderCompanionObject() {
100-
writer.withBlock("companion object {", "}") {
101-
write("operator fun invoke(block: Builder.() -> #Q): #Q = Builder().apply(block).build()", KotlinTypes.Unit, symbol)
100+
writer.withBlock("public companion object {", "}") {
101+
write("public operator fun invoke(block: Builder.() -> #Q): #Q = Builder().apply(block).build()", KotlinTypes.Unit, symbol)
102102
}
103103
}
104104

@@ -216,19 +216,19 @@ class StructureGenerator(
216216
// situation we have with constructors and positional arguments not playing well
217217
// with models evolving over time (e.g. new fields in different positions)
218218
writer.write("")
219-
.write("inline fun copy(block: Builder.() -> #Q = {}): #Q = Builder(this).apply(block).build()", KotlinTypes.Unit, symbol)
219+
.write("public inline fun copy(block: Builder.() -> #Q = {}): #Q = Builder(this).apply(block).build()", KotlinTypes.Unit, symbol)
220220
.write("")
221221
}
222222

223223
private fun renderBuilder() {
224224
writer.write("")
225-
.withBlock("class Builder {", "}") {
225+
.withBlock("public class Builder {", "}") {
226226
for (member in sortedMembers) {
227227
val (memberName, memberSymbol) = memberNameSymbolIndex[member]!!
228228
// we want the type names sans nullability (?) for arguments
229229
writer.renderMemberDocumentation(model, member)
230230
writer.renderAnnotations(member)
231-
write("var #L: #E", memberName, memberSymbol)
231+
write("public var #L: #E", memberName, memberSymbol)
232232
}
233233
write("")
234234

@@ -258,7 +258,7 @@ class StructureGenerator(
258258
val (memberName, memberSymbol) = memberNameSymbolIndex[member]!!
259259
writer.dokka("construct an [${memberSymbol.fullName}] inside the given [block]")
260260
writer.renderAnnotations(member)
261-
openBlock("fun #L(block: #Q.Builder.() -> #Q) {", memberName, memberSymbol, KotlinTypes.Unit)
261+
openBlock("public fun #L(block: #Q.Builder.() -> #Q) {", memberName, memberSymbol, KotlinTypes.Unit)
262262
.write("this.#L = #Q.invoke(block)", memberName, memberSymbol)
263263
.closeBlock("}")
264264
}
@@ -280,7 +280,7 @@ class StructureGenerator(
280280
val exceptionBaseClass = ExceptionBaseClassGenerator.baseExceptionSymbol(ctx.settings)
281281
writer.addImport(exceptionBaseClass)
282282

283-
writer.openBlock("class #T private constructor(builder: Builder) : ${exceptionBaseClass.name}() {", symbol)
283+
writer.openBlock("public class #T private constructor(builder: Builder) : ${exceptionBaseClass.name}() {", symbol)
284284
.write("")
285285
.call { renderImmutableProperties() }
286286
.write("")

0 commit comments

Comments
 (0)