Unverified Commit 5183ccbd authored by John DiSanti's avatar John DiSanti Committed by GitHub
Browse files

Split the `types` and `builders` modules into per-shape private modules (#2415)

parent 4c768473
Loading
Loading
Loading
Loading
+49 −9
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
package software.amazon.smithy.rust.codegen.client.smithy

import software.amazon.smithy.build.PluginContext
import software.amazon.smithy.codegen.core.Symbol
import software.amazon.smithy.model.Model
import software.amazon.smithy.model.knowledge.NullableIndex
import software.amazon.smithy.model.shapes.OperationShape
@@ -27,14 +28,20 @@ import software.amazon.smithy.rust.codegen.client.smithy.generators.protocol.Cli
import software.amazon.smithy.rust.codegen.client.smithy.protocols.ClientProtocolLoader
import software.amazon.smithy.rust.codegen.client.smithy.transformers.AddErrorMessage
import software.amazon.smithy.rust.codegen.client.smithy.transformers.RemoveEventStreamOperations
import software.amazon.smithy.rust.codegen.core.rustlang.EscapeFor
import software.amazon.smithy.rust.codegen.core.rustlang.RustModule
import software.amazon.smithy.rust.codegen.core.rustlang.RustReservedWords
import software.amazon.smithy.rust.codegen.core.rustlang.Writable
import software.amazon.smithy.rust.codegen.core.rustlang.implBlock
import software.amazon.smithy.rust.codegen.core.smithy.DirectedWalker
import software.amazon.smithy.rust.codegen.core.smithy.RustCrate
import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider
import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProviderConfig
import software.amazon.smithy.rust.codegen.core.smithy.contextName
import software.amazon.smithy.rust.codegen.core.smithy.generators.BuilderGenerator
import software.amazon.smithy.rust.codegen.core.smithy.generators.StructureGenerator
import software.amazon.smithy.rust.codegen.core.smithy.generators.UnionGenerator
import software.amazon.smithy.rust.codegen.core.smithy.module
import software.amazon.smithy.rust.codegen.core.smithy.protocols.ProtocolGeneratorFactory
import software.amazon.smithy.rust.codegen.core.smithy.transformers.EventStreamNormalizer
import software.amazon.smithy.rust.codegen.core.smithy.transformers.OperationNormalizer
@@ -45,6 +52,7 @@ import software.amazon.smithy.rust.codegen.core.util.hasTrait
import software.amazon.smithy.rust.codegen.core.util.isEventStream
import software.amazon.smithy.rust.codegen.core.util.letIf
import software.amazon.smithy.rust.codegen.core.util.runCommand
import software.amazon.smithy.rust.codegen.core.util.toSnakeCase
import java.util.logging.Logger

/**
@@ -182,6 +190,29 @@ class ClientCodegenVisitor(
    override fun getDefault(shape: Shape?) {
    }

    // TODO(CrateReorganization): Remove this function when cleaning up `enableNewCrateOrganizationScheme`
    private fun RustCrate.maybeInPrivateModuleWithReexport(
        privateModule: RustModule.LeafModule,
        symbol: Symbol,
        writer: Writable,
    ) {
        if (codegenContext.settings.codegenConfig.enableNewCrateOrganizationScheme) {
            inPrivateModuleWithReexport(privateModule, symbol, writer)
        } else {
            withModule(symbol.module(), writer)
        }
    }

    private fun privateModule(shape: Shape): RustModule.LeafModule =
        RustModule.private(privateModuleName(shape), parent = symbolProvider.moduleForShape(shape))

    private fun privateModuleName(shape: Shape): String =
        shape.contextName(codegenContext.serviceShape).let(this::privateModuleName)

    private fun privateModuleName(name: String): String =
        // Add the underscore to avoid colliding with public module names
        "_" + RustReservedWords.escapeIfNeeded(name.toSnakeCase(), EscapeFor.ModuleName)

    /**
     * Structure Shape Visitor
     *
@@ -192,9 +223,9 @@ class ClientCodegenVisitor(
     * This function _does not_ generate any serializers
     */
    override fun structureShape(shape: StructureShape) {
        when (val errorTrait = shape.getTrait<ErrorTrait>()) {
        val (renderStruct, renderBuilder) = when (val errorTrait = shape.getTrait<ErrorTrait>()) {
            null -> {
                rustCrate.useShapeWriter(shape) {
                val struct: Writable = {
                    StructureGenerator(
                        model,
                        symbolProvider,
@@ -207,8 +238,7 @@ class ClientCodegenVisitor(
                        BuilderGenerator.renderConvenienceMethod(this, symbolProvider, shape)
                    }
                }

                rustCrate.withModule(symbolProvider.moduleForBuilder(shape)) {
                val builder: Writable = {
                    BuilderGenerator(
                        codegenContext.model,
                        codegenContext.symbolProvider,
@@ -216,17 +246,26 @@ class ClientCodegenVisitor(
                        codegenDecorator.builderCustomizations(codegenContext, emptyList()),
                    ).render(this)
                }
                struct to builder
            }
            else -> {
                ErrorGenerator(
                    rustCrate,
                val errorGenerator = ErrorGenerator(
                    model,
                    symbolProvider,
                    shape,
                    errorTrait,
                    codegenDecorator.errorImplCustomizations(codegenContext, emptyList()),
                ).render()
                )
                errorGenerator::renderStruct to errorGenerator::renderBuilder
            }
        }

        val privateModule = privateModule(shape)
        rustCrate.maybeInPrivateModuleWithReexport(privateModule, symbolProvider.toSymbol(shape)) {
            renderStruct(this)
        }
        rustCrate.maybeInPrivateModuleWithReexport(privateModule, symbolProvider.symbolForBuilder(shape)) {
            renderBuilder(this)
        }
    }

@@ -237,7 +276,8 @@ class ClientCodegenVisitor(
     */
    override fun stringShape(shape: StringShape) {
        if (shape.hasTrait<EnumTrait>()) {
            rustCrate.useShapeWriter(shape) {
            val privateModule = privateModule(shape)
            rustCrate.maybeInPrivateModuleWithReexport(privateModule, symbolProvider.toSymbol(shape)) {
                ClientEnumGenerator(codegenContext, shape).render(this)
            }
        }
@@ -251,7 +291,7 @@ class ClientCodegenVisitor(
     * Note: this does not generate serializers
     */
    override fun unionShape(shape: UnionShape) {
        rustCrate.useShapeWriter(shape) {
        rustCrate.maybeInPrivateModuleWithReexport(privateModule(shape), symbolProvider.toSymbol(shape)) {
            UnionGenerator(model, symbolProvider, this, shape, renderUnknownVariant = true).render()
        }
        if (shape.isEventStream()) {
+16 −8
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ package software.amazon.smithy.rust.codegen.client.smithy.generators.error
import software.amazon.smithy.model.Model
import software.amazon.smithy.model.shapes.StructureShape
import software.amazon.smithy.model.traits.ErrorTrait
import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter
import software.amazon.smithy.rust.codegen.core.rustlang.Writable
import software.amazon.smithy.rust.codegen.core.rustlang.implBlock
import software.amazon.smithy.rust.codegen.core.rustlang.rust
@@ -17,7 +18,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.writable
import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.errorMetadata
import software.amazon.smithy.rust.codegen.core.smithy.RustCrate
import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider
import software.amazon.smithy.rust.codegen.core.smithy.generators.BuilderCustomization
import software.amazon.smithy.rust.codegen.core.smithy.generators.BuilderGenerator
@@ -29,7 +29,6 @@ import software.amazon.smithy.rust.codegen.core.smithy.generators.error.ErrorImp
import software.amazon.smithy.rust.codegen.core.smithy.generators.error.ErrorImplGenerator

class ErrorGenerator(
    private val rustCrate: RustCrate,
    private val model: Model,
    private val symbolProvider: RustSymbolProvider,
    private val shape: StructureShape,
@@ -37,11 +36,10 @@ class ErrorGenerator(
    private val implCustomizations: List<ErrorImplCustomization>,
) {
    private val runtimeConfig = symbolProvider.config.runtimeConfig
    private val symbol = symbolProvider.toSymbol(shape)

    fun render() {
        val symbol = symbolProvider.toSymbol(shape)

        rustCrate.useShapeWriter(shape) {
    fun renderStruct(writer: RustWriter) {
        writer.apply {
            StructureGenerator(
                model, symbolProvider, this, shape,
                listOf(
@@ -55,6 +53,7 @@ class ErrorGenerator(
                                is StructureSection.AdditionalDebugFields -> {
                                    rust("""${section.formatterName}.field("meta", &self.meta);""")
                                }

                                else -> {}
                            }
                        }
@@ -62,7 +61,14 @@ class ErrorGenerator(
                ),
            ).render()

            ErrorImplGenerator(model, symbolProvider, this, shape, error, implCustomizations).render(CodegenTarget.CLIENT)
            ErrorImplGenerator(
                model,
                symbolProvider,
                this,
                shape,
                error,
                implCustomizations,
            ).render(CodegenTarget.CLIENT)

            rustBlock("impl #T for ${symbol.name}", RuntimeType.provideErrorMetadataTrait(runtimeConfig)) {
                rust("fn meta(&self) -> &#T { &self.meta }", errorMetadata(runtimeConfig))
@@ -72,8 +78,10 @@ class ErrorGenerator(
                BuilderGenerator.renderConvenienceMethod(this, symbolProvider, shape)
            }
        }
    }

        rustCrate.withModule(symbolProvider.moduleForBuilder(shape)) {
    fun renderBuilder(writer: RustWriter) {
        writer.apply {
            BuilderGenerator(
                model, symbolProvider, shape,
                listOf(
+8 −3
Original line number Diff line number Diff line
@@ -81,13 +81,18 @@ abstract class ClientEventStreamBaseRequirements : EventStreamTestRequirements<C
        shape: StructureShape,
    ) {
        val errorTrait = shape.expectTrait<ErrorTrait>()
        ErrorGenerator(
            rustCrate,
        val errorGenerator = ErrorGenerator(
            codegenContext.model,
            codegenContext.symbolProvider,
            shape,
            errorTrait,
            emptyList(),
        ).render()
        )
        rustCrate.useShapeWriter(shape) {
            errorGenerator.renderStruct(this)
        }
        rustCrate.withModule(codegenContext.symbolProvider.moduleForBuilder(shape)) {
            errorGenerator.renderBuilder(this)
        }
    }
}
+20 −8
Original line number Diff line number Diff line
@@ -101,6 +101,11 @@ class RustReservedWordSymbolProvider(private val base: RustSymbolProvider) : Wra
    }
}

enum class EscapeFor {
    TypeName,
    ModuleName,
}

object RustReservedWords : ReservedWords {
    private val RustKeywords = setOf(
        "as",
@@ -169,13 +174,20 @@ object RustReservedWords : ReservedWords {
        "SelfValue" to "SelfValue_",
    )

    override fun escape(word: String): String = when (val mapped = keywordEscapingMap[word]) {
        null -> "r##$word"
    override fun escape(word: String): String = doEscape(word, EscapeFor.TypeName)

    private fun doEscape(word: String, escapeFor: EscapeFor = EscapeFor.TypeName): String =
        when (val mapped = keywordEscapingMap[word]) {
            null -> when (escapeFor) {
                EscapeFor.TypeName -> "r##$word"
                EscapeFor.ModuleName -> "${word}_"
            }
            else -> mapped
        }

    fun escapeIfNeeded(word: String): String = when (isReserved(word)) {
        true -> escape(word)
    fun escapeIfNeeded(word: String, escapeFor: EscapeFor = EscapeFor.TypeName): String =
        when (isReserved(word)) {
            true -> doEscape(word, escapeFor)
            else -> word
        }

+18 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
package software.amazon.smithy.rust.codegen.core.smithy

import software.amazon.smithy.build.FileManifest
import software.amazon.smithy.codegen.core.Symbol
import software.amazon.smithy.codegen.core.SymbolProvider
import software.amazon.smithy.codegen.core.WriterDelegator
import software.amazon.smithy.model.Model
@@ -18,6 +19,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.RustDependency
import software.amazon.smithy.rust.codegen.core.rustlang.RustModule
import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter
import software.amazon.smithy.rust.codegen.core.rustlang.Writable
import software.amazon.smithy.rust.codegen.core.rustlang.rust
import software.amazon.smithy.rust.codegen.core.smithy.generators.CargoTomlGenerator
import software.amazon.smithy.rust.codegen.core.smithy.generators.LibRsCustomization
import software.amazon.smithy.rust.codegen.core.smithy.generators.LibRsGenerator
@@ -183,6 +185,22 @@ open class RustCrate(
            fileWriter(it)
        }
    }

    /**
     * Render something in a private module and re-export it into the given symbol.
     *
     * @param privateModule: Private module to render into
     * @param symbol: The symbol of the thing being rendered, which will be re-exported. This symbol
     * should be the public-facing symbol rather than the private symbol.
     */
    fun inPrivateModuleWithReexport(privateModule: RustModule.LeafModule, symbol: Symbol, writer: Writable) {
        withModule(privateModule, writer)
        privateModule.toType().resolve(symbol.name).toSymbol().also { privateSymbol ->
            withModule(symbol.module()) {
                rust("pub use #T;", privateSymbol)
            }
        }
    }
}

// TODO(https://github.com/awslabs/smithy-rs/issues/2341): Remove unconstrained/constrained from codegen-core