Skip to content

Commit

Permalink
Fix ServerAdditionalSettings to allow method calls in any order
Browse files Browse the repository at this point in the history
Previously, calling generateCodegenComments() before other methods would
fail because it returned the parent type. Modified the class to maintain
the correct type throughout method chaining.
  • Loading branch information
Fahad Zubair committed Nov 21, 2024
1 parent aac9bec commit 8eae004
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,97 +40,73 @@ data class IntegrationTestParams(
* model,
* IntegrationTestParams(
* additionalSettings =
* ServerAdditionalSettings.builder()
* .generateCodegenComments()
* .publicConstrainedTypes()
* ServerAdditionalSettings()
* .generateCodegenComments(true)
* .publicConstrainedTypes(true)
* .toObjectNode()
* )),
* ```
*/
sealed class AdditionalSettings {
abstract fun toObjectNode(): ObjectNode

abstract class CoreAdditionalSettings protected constructor(val settings: List<AdditionalSettings>) : AdditionalSettings() {
override fun toObjectNode(): ObjectNode {
val merged =
settings.map { it.toObjectNode() }
.reduce { acc, next -> acc.merge(next) }

return ObjectNode.builder()
.withMember("codegen", merged)
.build()
}

abstract class Builder<T : CoreAdditionalSettings> : AdditionalSettings() {
protected val settings = mutableListOf<AdditionalSettings>()

fun generateCodegenComments(debugMode: Boolean = true): Builder<T> {
settings.add(GenerateCodegenComments(debugMode))
return this
}

abstract fun build(): T

override fun toObjectNode(): ObjectNode = build().toObjectNode()
open class AdditionalSettings<T : AdditionalSettings<T>> {
private val codegenBuilderDelegate =
lazy {
ObjectNode.builder()
}
private val codegenBuilder: ObjectNode.Builder by codegenBuilderDelegate

// Core settings that are common to both Servers and Clients should be defined here.
data class GenerateCodegenComments(val debugMode: Boolean) : AdditionalSettings() {
override fun toObjectNode(): ObjectNode =
ObjectNode.builder()
.withMember("debugMode", debugMode)
.build()
fun build(): ObjectNode {
return if (codegenBuilderDelegate.isInitialized()) {
ObjectNode.builder()
.withMember("codegen", codegenBuilder.build())
.build()
} else {
ObjectNode.builder().build()
}
}
}

class ClientAdditionalSettings private constructor(settings: List<AdditionalSettings>) :
AdditionalSettings.CoreAdditionalSettings(settings) {
class Builder : CoreAdditionalSettings.Builder<ClientAdditionalSettings>() {
override fun build(): ClientAdditionalSettings = ClientAdditionalSettings(settings)
}

// Additional settings that are specific to client generation should be defined here.

companion object {
fun builder() = Builder()
}
@Suppress("UNCHECKED_CAST")
open fun generateCodegenComments(debugMode: Boolean = true): T {
codegenBuilder.withMember("debugMode", debugMode)
return this as T
}

class ServerAdditionalSettings private constructor(settings: List<AdditionalSettings>) :
AdditionalSettings.CoreAdditionalSettings(settings) {
class Builder : CoreAdditionalSettings.Builder<ServerAdditionalSettings>() {
fun publicConstrainedTypes(enabled: Boolean = true): Builder {
settings.add(PublicConstrainedTypes(enabled))
return this
}
@Suppress("UNCHECKED_CAST")
protected fun withCodegenMember(
key: String,
value: Boolean,
): T {
codegenBuilder.withMember(key, value)
return this as T
}

fun addValidationExceptionToConstrainedOperations(enabled: Boolean = true): Builder {
settings.add(AddValidationExceptionToConstrainedOperations(enabled))
return this
}
@Suppress("UNCHECKED_CAST")
protected fun withCodegenMember(
key: String,
value: String,
): T {
codegenBuilder.withMember(key, value)
return this as T
}

override fun build(): ServerAdditionalSettings = ServerAdditionalSettings(settings)
}
@Suppress("UNCHECKED_CAST")
protected fun withCodegenMember(
key: String,
value: Number,
): T {
codegenBuilder.withMember(key, value)
return this as T
}
}

private data class PublicConstrainedTypes(val enabled: Boolean) : AdditionalSettings() {
override fun toObjectNode(): ObjectNode =
ObjectNode.builder()
.withMember("publicConstrainedTypes", enabled)
.build()
}
class ServerAdditionalSettings : AdditionalSettings<ServerAdditionalSettings>() {
fun publicConstrainedTypes(enabled: Boolean = true): ServerAdditionalSettings =
withCodegenMember("publicConstrainedTypes", enabled)

private data class AddValidationExceptionToConstrainedOperations(val enabled: Boolean) : AdditionalSettings() {
override fun toObjectNode(): ObjectNode =
ObjectNode.builder()
.withMember("addValidationExceptionToConstrainedOperations", enabled)
.build()
}
fun addValidationExceptionToConstrainedOperations(enabled: Boolean = true) =
withCodegenMember("addValidationExceptionToConstrainedOperations", enabled)

companion object {
fun builder() = Builder()
}
}
fun ignoreUnsupportedConstraints() = withCodegenMember("ignoreUnsupportedConstraints", true)
}

/**
* Run cargo test on a true, end-to-end, codegen product of a given model.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,9 +242,9 @@ class ConstraintsTest {
IntegrationTestParams(
service = "test#SampleService",
additionalSettings =
ServerAdditionalSettings.builder()
ServerAdditionalSettings()
.publicConstrainedTypes(pubConstraints)
.toObjectNode(),
.build(),
overrideTestDir = dir,
),
test = test,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,10 @@ internal class AddValidationExceptionToConstrainedOperationsTest {
testModelWithValidationExceptionImported,
IntegrationTestParams(
additionalSettings =
ServerAdditionalSettings.builder()
ServerAdditionalSettings()
.generateCodegenComments(true)
.addValidationExceptionToConstrainedOperations()
.toObjectNode(),
.build(),
),
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package software.amazon.smithy.rust.codegen.server.smithy.protocols.serialize

import org.junit.jupiter.api.Test
import software.amazon.smithy.rust.codegen.core.testutil.IntegrationTestParams
import software.amazon.smithy.rust.codegen.core.testutil.ServerAdditionalSettings
import software.amazon.smithy.rust.codegen.server.smithy.ModelProtocol
import software.amazon.smithy.rust.codegen.server.smithy.loadSmithyConstraintsModelForProtocol
import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverIntegrationTest
Expand All @@ -20,7 +19,6 @@ class CborConstraintsIntegrationTest {
model,
IntegrationTestParams(
service = serviceShape.toString(),
additionalSettings = ServerAdditionalSettings.builder().generateCodegenComments().toObjectNode(),
),
) { _, _ ->
}
Expand Down

0 comments on commit 8eae004

Please sign in to comment.