From b490740a801d50bf02b7a761d5a401d2fa894ad4 Mon Sep 17 00:00:00 2001 From: Fahad Zubair Date: Fri, 27 Jan 2023 10:28:11 +0000 Subject: [PATCH 01/18] Constraint member types are refactored as standalone shapes. --- .../ClientEventStreamBaseRequirements.kt | 2 + .../core/testutil/EventStreamTestTools.kt | 2 + .../smithy/ConstrainedShapeSymbolProvider.kt | 80 ++- .../ConstraintViolationSymbolProvider.kt | 28 +- .../rust/codegen/server/smithy/Constraints.kt | 60 +++ .../RustCrateInlineModuleComposingWriter.kt | 321 ++++++++++++ .../server/smithy/RustServerCodegenPlugin.kt | 3 +- .../server/smithy/ServerCodegenVisitor.kt | 160 ++++-- .../server/smithy/ServerSymbolProviders.kt | 8 +- .../UnconstrainedShapeSymbolProvider.kt | 7 +- .../smithy/ValidateUnsupportedConstraints.kt | 18 +- .../CollectionConstraintViolationGenerator.kt | 5 +- .../generators/ConstrainedBlobGenerator.kt | 4 +- .../generators/ConstrainedNumberGenerator.kt | 6 +- .../generators/ConstrainedStringGenerator.kt | 7 +- .../MapConstraintViolationGenerator.kt | 6 +- .../PubCrateConstrainedCollectionGenerator.kt | 5 +- .../PubCrateConstrainedMapGenerator.kt | 5 +- .../generators/ServerBuilderGenerator.kt | 10 +- ...rGeneratorWithoutPublicConstrainedTypes.kt | 8 +- .../smithy/generators/ServerBuilderSymbol.kt | 9 +- .../UnconstrainedCollectionGenerator.kt | 5 +- .../generators/UnconstrainedMapGenerator.kt | 5 +- .../generators/UnconstrainedUnionGenerator.kt | 12 +- .../protocol/ServerProtocolTestGenerator.kt | 71 +-- .../smithy/testutil/ServerTestHelpers.kt | 9 +- ...eticStructureFromConstrainedMemberTrait.kt | 16 + .../ConstrainedMemberTransform.kt | 222 +++++++++ .../smithy/ConstraintsMemberShapeTest.kt | 468 ++++++++++++++++++ ...ustCrateInlineModuleComposingWriterTest.kt | 259 ++++++++++ ...ateUnsupportedConstraintsAreNotUsedTest.kt | 33 -- .../ConstrainedBlobGeneratorTest.kt | 13 +- .../ConstrainedCollectionGeneratorTest.kt | 4 +- .../generators/ConstrainedMapGeneratorTest.kt | 4 +- .../ConstrainedNumberGeneratorTest.kt | 7 +- .../ConstrainedStringGeneratorTest.kt | 10 + .../ServerBuilderDefaultValuesTest.kt | 13 +- .../generators/ServerBuilderGeneratorTest.kt | 10 +- .../generators/ServerInstantiatorTest.kt | 7 +- .../ServerOperationErrorGeneratorTest.kt | 2 +- .../UnconstrainedCollectionGeneratorTest.kt | 15 +- .../UnconstrainedMapGeneratorTest.kt | 15 +- .../UnconstrainedUnionGeneratorTest.kt | 8 +- .../ServerEventStreamBaseRequirements.kt | 7 +- ...verEventStreamUnmarshallerGeneratorTest.kt | 2 + 45 files changed, 1743 insertions(+), 228 deletions(-) create mode 100644 codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt create mode 100644 codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/traits/SyntheticStructureFromConstrainedMemberTrait.kt create mode 100644 codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/transformers/ConstrainedMemberTransform.kt create mode 100644 codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt create mode 100644 codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamBaseRequirements.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamBaseRequirements.kt index 34efa20475..ff546f904f 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamBaseRequirements.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamBaseRequirements.kt @@ -23,6 +23,7 @@ import software.amazon.smithy.rust.codegen.client.testutil.testSymbolProvider import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.implBlock import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget +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.BuilderGenerator import software.amazon.smithy.rust.codegen.core.testutil.EventStreamTestModels @@ -51,6 +52,7 @@ abstract class ClientEventStreamBaseRequirements : EventStreamTestRequirements { /** Render a builder for the given shape */ fun renderBuilderForShape( + rustCrate: RustCrate, writer: RustWriter, codegenContext: C, shape: StructureShape, diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt index a2e1fdb709..756b659ef9 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt @@ -19,7 +19,10 @@ import software.amazon.smithy.model.shapes.ServiceShape import software.amazon.smithy.model.shapes.Shape import software.amazon.smithy.model.shapes.ShortShape import software.amazon.smithy.model.shapes.StringShape +import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.model.traits.LengthTrait +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.RustType import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.WrappingSymbolProvider @@ -32,6 +35,8 @@ import software.amazon.smithy.rust.codegen.core.smithy.symbolBuilder import software.amazon.smithy.rust.codegen.core.util.hasTrait import software.amazon.smithy.rust.codegen.core.util.orNull import software.amazon.smithy.rust.codegen.core.util.toPascalCase +import software.amazon.smithy.rust.codegen.core.util.toSnakeCase +import software.amazon.smithy.rust.codegen.server.smithy.generators.serverBuilderModule /** * The [ConstrainedShapeSymbolProvider] returns, for a given _directly_ @@ -56,14 +61,19 @@ class ConstrainedShapeSymbolProvider( private val base: RustSymbolProvider, private val model: Model, private val serviceShape: ServiceShape, + private val publicConstrainedTypes : Boolean = true ) : WrappingSymbolProvider(base) { private val nullableIndex = NullableIndex.of(model) private fun publicConstrainedSymbolForMapOrCollectionShape(shape: Shape): Symbol { check(shape is MapShape || shape is CollectionShape) + // FZ rebase + // val rustType = RustType.Opaque(shape.contextName(serviceShape).toPascalCase()) + // return symbolBuilder(shape, rustType).locatedIn(ServerRustModule.Model).build() - val rustType = RustType.Opaque(shape.contextName(serviceShape).toPascalCase()) - return symbolBuilder(shape, rustType).locatedIn(ServerRustModule.Model).build() + val (name, module) = getMemberNameAndModule(shape, serviceShape, ServerRustModule.Model, !publicConstrainedTypes) + val rustType = RustType.Opaque(name) + return symbolBuilder(shape, rustType).locatedIn(module).build() } override fun toSymbol(shape: Shape): Symbol { @@ -74,8 +84,14 @@ class ConstrainedShapeSymbolProvider( val target = model.expectShape(shape.target) val targetSymbol = this.toSymbol(target) // Handle boxing first, so we end up with `Option>`, not `Box>`. - handleOptionality(handleRustBoxing(targetSymbol, shape), shape, nullableIndex, base.config().nullabilityCheckMode) + handleOptionality( + handleRustBoxing(targetSymbol, shape), + shape, + nullableIndex, + base.config().nullabilityCheckMode, + ) } + is MapShape -> { if (shape.isDirectlyConstrained(base)) { check(shape.hasTrait()) { @@ -91,6 +107,7 @@ class ConstrainedShapeSymbolProvider( .build() } } + is CollectionShape -> { if (shape.isDirectlyConstrained(base)) { check(constrainedCollectionCheck(shape)) { @@ -105,8 +122,15 @@ class ConstrainedShapeSymbolProvider( is StringShape, is IntegerShape, is ShortShape, is LongShape, is ByteShape, is BlobShape -> { if (shape.isDirectlyConstrained(base)) { - val rustType = RustType.Opaque(shape.contextName(serviceShape).toPascalCase()) - symbolBuilder(shape, rustType).locatedIn(ServerRustModule.Model).build() + // FZ rebase + //val rustType = RustType.Opaque(shape.contextName(serviceShape).toPascalCase()) + //symbolBuilder(shape, rustType).locatedIn(ServerRustModule.Model).build() + + // A standalone constrained shape goes into `ModelsModule`, but one + // arising from a constrained member shape goes into a module for the container. + val (name, module) = getMemberNameAndModule(shape, serviceShape, ServerRustModule.Model, !publicConstrainedTypes) + val rustType = RustType.Opaque(name) + symbolBuilder(shape, rustType).locatedIn(module).build() } else { base.toSymbol(shape) } @@ -122,9 +146,51 @@ class ConstrainedShapeSymbolProvider( * - That it has no unsupported constraints applied. */ private fun constrainedCollectionCheck(shape: CollectionShape): Boolean { - val supportedConstraintTraits = supportedCollectionConstraintTraits.mapNotNull { shape.getTrait(it).orNull() }.toSet() + val supportedConstraintTraits = + supportedCollectionConstraintTraits.mapNotNull { shape.getTrait(it).orNull() }.toSet() val allConstraintTraits = allConstraintTraits.mapNotNull { shape.getTrait(it).orNull() }.toSet() - return supportedConstraintTraits.isNotEmpty() && allConstraintTraits.subtract(supportedConstraintTraits).isEmpty() + return supportedConstraintTraits.isNotEmpty() && allConstraintTraits.subtract(supportedConstraintTraits) + .isEmpty() + } + + + /** + * Returns the pair (Rust Symbol Name, Inline Module) for the shape. At the time of model transformation all + * constrained member shapes are extracted and are given a model-wide unique name. However, the generated code + * for the new shapes is in a module that is named after the containing shape (structure, list, map or union). + * The new shape's Rust Symbol is renamed from `{structureName}{memberName}` to `{structure_name}::{member_name}` + */ + private fun getMemberNameAndModule( + shape: Shape, + serviceShape: ServiceShape, + defaultModule: RustModule.LeafModule, + pubCrateServerBuilder: Boolean, + ): Pair { + val (container, member) = + shape.overriddenConstrainedMemberInfo() ?: return Pair(shape.contextName(serviceShape), defaultModule) + + return if (container is StructureShape) { + val builderModule = container.serverBuilderModule(base, pubCrateServerBuilder) + val renameTo = member.memberName ?: member.id.name + Pair(renameTo.toPascalCase(), builderModule) + } else { + // For List, Union and Map, the new shape defined for a constrained member shape + // need to be placed into an inline module named `pub {container_name_in_snake_case}` + val innerModuleName = RustReservedWords.escapeIfNeeded(container.id.name.toSnakeCase()) + if (pubCrateServerBuilder) { + "_internal" + } else { + "" + } + + val innerModule = RustModule.new( + innerModuleName, + visibility = Visibility.publicIf(!pubCrateServerBuilder, Visibility.PUBCRATE), + parent = defaultModule, + inline = true, + ) + val renameTo = member.memberName ?: member.id.name + Pair(renameTo.toPascalCase(), innerModule) + } } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt index 12d838db54..83fa724605 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt @@ -29,8 +29,10 @@ import software.amazon.smithy.rust.codegen.core.smithy.contextName import software.amazon.smithy.rust.codegen.core.smithy.locatedIn import software.amazon.smithy.rust.codegen.core.smithy.module import software.amazon.smithy.rust.codegen.core.smithy.rustType +import software.amazon.smithy.rust.codegen.core.util.getTrait import software.amazon.smithy.rust.codegen.core.util.toSnakeCase import software.amazon.smithy.rust.codegen.server.smithy.generators.serverBuilderSymbol +import software.amazon.smithy.rust.codegen.server.smithy.traits.SyntheticStructureFromConstrainedMemberTrait /** * The [ConstraintViolationSymbolProvider] returns, for a given constrained @@ -79,14 +81,34 @@ class ConstraintViolationSymbolProvider( private fun Shape.shapeModule(): RustModule.LeafModule { val documentation = if (publicConstrainedTypes && this.isDirectlyConstrained(base)) { - "See [`${this.contextName(serviceShape)}`]." + if (this.hasTrait(SyntheticStructureFromConstrainedMemberTrait.ID)) { + val symbol = base.toSymbol(this) + "See [`${this.contextName(serviceShape)}`]($symbol)." + } else { + "See [`${this.contextName(serviceShape)}`]." + } } else { null } - return RustModule.new( + + val syntheticTrait = getTrait() + + val (module, name) = if (syntheticTrait != null) { + // For constrained member shapes, the ConstraintViolation code needs to go in an inline rust module + // that is a descendant of the module that contains the extracted shape itself. + val overriddenMemberModule = this.getParentAndInlineModuleForConstrainedMember(base, !publicConstrainedTypes)!! + val name = syntheticTrait.member.memberName + Pair(overriddenMemberModule.second, RustReservedWords.escapeIfNeeded(name).toSnakeCase()) + } else { // Need to use the context name so we get the correct name for maps. - name = RustReservedWords.escapeIfNeeded(this.contextName(serviceShape)).toSnakeCase(), + Pair(ModelsModule, RustReservedWords.escapeIfNeeded(this.contextName(serviceShape)).toSnakeCase()) + } + + return RustModule.new( + name = name, visibility = visibility, + // FZ rebase + //parent = ServerRustModule.Model, parent = ServerRustModule.Model, inline = true, documentation = documentation, diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt index f6cc943a9c..800c171ab8 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt @@ -14,6 +14,7 @@ import software.amazon.smithy.model.shapes.IntegerShape import software.amazon.smithy.model.shapes.LongShape import software.amazon.smithy.model.shapes.MapShape import software.amazon.smithy.model.shapes.MemberShape +import software.amazon.smithy.model.shapes.ServiceShape import software.amazon.smithy.model.shapes.Shape import software.amazon.smithy.model.shapes.ShortShape import software.amazon.smithy.model.shapes.SimpleShape @@ -26,11 +27,21 @@ import software.amazon.smithy.model.traits.PatternTrait import software.amazon.smithy.model.traits.RangeTrait import software.amazon.smithy.model.traits.RequiredTrait import software.amazon.smithy.model.traits.UniqueItemsTrait +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.Visibility import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext import software.amazon.smithy.rust.codegen.core.smithy.DirectedWalker +import software.amazon.smithy.rust.codegen.core.smithy.ModelsModule +import software.amazon.smithy.rust.codegen.core.smithy.contextName import software.amazon.smithy.rust.codegen.core.smithy.isOptional +import software.amazon.smithy.rust.codegen.core.smithy.module import software.amazon.smithy.rust.codegen.core.util.UNREACHABLE +import software.amazon.smithy.rust.codegen.core.util.getTrait import software.amazon.smithy.rust.codegen.core.util.hasTrait +import software.amazon.smithy.rust.codegen.core.util.toSnakeCase +import software.amazon.smithy.rust.codegen.server.smithy.generators.serverBuilderModule +import software.amazon.smithy.rust.codegen.server.smithy.traits.SyntheticStructureFromConstrainedMemberTrait /** * This file contains utilities to work with constrained shapes. @@ -160,3 +171,52 @@ fun Shape.typeNameContainsNonPublicType( is StructureShape, is UnionShape -> false else -> UNREACHABLE("the above arms should be exhaustive, but we received shape: $this") } + + +/** + * For synthetic shapes that are added to the model because of member constrained shapes, it returns + * the "container" and "the member shape" that originally had the constraint trait. For all other + * shapes, it returns null. + */ +fun Shape.overriddenConstrainedMemberInfo(): Pair? { + val trait = getTrait() ?: return null + return Pair(trait.container, trait.member) +} + + +/** + * Returns the parent and the inline module that this particular shape should go in. + */ +fun Shape.getParentAndInlineModuleForConstrainedMember(symbolProvider: SymbolProvider, pubCrateServerBuilder: Boolean): Pair? { + //val container = overriddenConstrainedMemberInfo()?.first ?: return null + val overriddenTrait = getTrait() ?: return null + return if (overriddenTrait.container is StructureShape) { + val structureModule = symbolProvider.toSymbol(overriddenTrait.container).module() + val builderModule = overriddenTrait.container.serverBuilderModule(symbolProvider, pubCrateServerBuilder) + Pair(structureModule, builderModule) + } + else { + // For constrained member shapes, the ConstraintViolation code needs to go in an inline rust module + // that is a descendant of the module that contains the extracted shape itself. + return if (!pubCrateServerBuilder) { + // List, union and map types need to go into their own module + val shapeSymbol = symbolProvider.toSymbol(this) + val shapeModule = shapeSymbol.module() + check(!shapeModule.parent.isInline()) { + "parent module of $id should not be an inline module" + } + Pair(shapeModule.parent as RustModule.LeafModule, shapeModule) + } + else { + val name = RustReservedWords.escapeIfNeeded(overriddenTrait.container.id.name).toSnakeCase() + "_internal" + val innerModule = RustModule.new( + name = name, + visibility = Visibility.PUBCRATE, + parent = ModelsModule, + inline = true, + ) + + Pair(ModelsModule, innerModule) + } + } +} diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt new file mode 100644 index 0000000000..b0081979d2 --- /dev/null +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt @@ -0,0 +1,321 @@ +package software.amazon.smithy.rust.codegen.server.smithy + +import software.amazon.smithy.codegen.core.Symbol +import software.amazon.smithy.model.shapes.Shape +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.smithy.RustCrate +import software.amazon.smithy.rust.codegen.core.smithy.module +import java.util.concurrent.ConcurrentHashMap + +typealias DocWriter = () -> Any +typealias InlineModuleCreator = (Symbol, Writable) -> Unit + + +/** + * Initializes RustCrate -> InnerModule data structure. + */ +fun RustCrate.initializeInlineModuleWriter(debugMode : Boolean): InnerModule = + crateToInlineModule + .getOrPut(this) { InnerModule(debugMode) } + +/** + * Returns the InnerModule for the given RustCrate + */ +fun RustCrate.getInlineModuleWriter() : InnerModule { + return crateToInlineModule.getOrPut(this) { InnerModule(false) } +} + +/** + * Returns a function that can be used to create an inline module writer. + */ +fun RustCrate.createInlineModuleCreator(): InlineModuleCreator { + return { symbol: Symbol, writable: Writable -> + this.getInlineModuleWriter().withInlineModuleHierarchyUsingCrate(this, symbol.module()) { + writable() + } + } +} + +/** + * If the passed in `shape` is a synthetic extracted shape resulting from a constrained struct member, + * the `Writable` is called using the structure's builder module. Otherwise the `Writable` is called + * using the given `module`. + */ +fun RustCrate.withModuleOrWithStructureBuilderModule( + module: RustModule, + shape: Shape, + codegenContext: ServerCodegenContext, + codeWritable: Writable, +) { + // All structure constrained-member-shapes code is generated inside the structure builder's module. + val parentAndInlineModuleInfo = + shape.getParentAndInlineModuleForConstrainedMember(codegenContext.symbolProvider, !codegenContext.settings.codegenConfig.publicConstrainedTypes) + if (parentAndInlineModuleInfo == null) { + this.withModule(module, codeWritable) + } else { + val (parent, inline) = parentAndInlineModuleInfo + val inlineWriter = this.getInlineModuleWriter() + + inlineWriter.withInlineModuleHierarchyUsingCrate(this, parent) { + inlineWriter.withInlineModuleHierarchy(this, inline) { + codeWritable(this) + } + } + } +} + +/** + * If the passed in `shape` is a synthetic extracted shape resulting from a constrained struct member, + * the `Writable` is called using the structure's builder module. Otherwise the `Writable` is called + * using shape's `module`. + */ +fun RustCrate.useShapeWriterOrUseWithStructureBuilder( + shape: Shape, + codegenContext: ServerCodegenContext, + docWriter: DocWriter? = null, + writable: Writable, +) { + // All structure constrained-member-shapes code is generated inside the structure builder's module. + val parentAndInlineModuleInfo = + shape.getParentAndInlineModuleForConstrainedMember(codegenContext.symbolProvider, !codegenContext.settings.codegenConfig.publicConstrainedTypes) + if (parentAndInlineModuleInfo == null) { + docWriter?.invoke() + this.useShapeWriter(shape, writable) + } else { + val (parent, inline) = parentAndInlineModuleInfo + val inlineWriter = this.getInlineModuleWriter() + + inlineWriter.withInlineModuleHierarchyUsingCrate(this, parent) { + inlineWriter.withInlineModuleHierarchy(this, inline) { + writable(this) + } + } + } +} + +/** + * Given a `RustWriter` calls the `Writable` using a `RustWriter` for the `inlineModule` + */ +fun RustCrate.withInMemoryInlineModule( + outerWriter: RustWriter, + inlineModule: RustModule.LeafModule, + docWriter: DocWriter?, + codeWritable: Writable, +) { + check(inlineModule.isInline()) { + "module has to be an inline module for it to be used with the InlineModuleWriter" + } + this.getInlineModuleWriter().withInlineModuleHierarchy(outerWriter, inlineModule, docWriter) { + codeWritable(this) + } +} + +fun RustWriter.createTestInlineModuleCreator(): InlineModuleCreator { + return { symbol: Symbol, writable: Writable -> + this.withInlineModule(symbol.module()) { + writable() + } + } +} + +/** + * Maintains the `RustWriter` that has been created for a `RustModule.LeafModule`. + */ +private data class InlineModuleWithWriter(val inlineModule : RustModule.LeafModule, val writer : RustWriter) + +/** + * For each RustCrate a separate mapping of inline-module to `RustWriter` is maintained. + */ +private val crateToInlineModule: ConcurrentHashMap = + ConcurrentHashMap() + +class InnerModule(private val debugMode : Boolean) { + private val topLevelModuleWriters: MutableSet = mutableSetOf() + private val inlineModuleWriters: HashMap> = hashMapOf() + private val docWriters: HashMap> = hashMapOf() + private val writerCreator = RustWriter.factory(debugMode) + private val emptyLineCount: Int = writerCreator + .apply("lines-it-always-writes.rs", "crate") + .toString() + .split("\n")[0] + .length + + private fun createNewInlineModule(): RustWriter { + val writer = writerCreator.apply("unknown-module-would-never-be-written.rs", "crate") + // There has never been a child of the top most inner module, hence create a new one + inlineModuleWriters[writer] = mutableListOf() + return writer + } + + fun withInlineModule(outerWriter: RustWriter, innerModule: RustModule.LeafModule, docWriter: DocWriter? = null, writable: Writable) { + if (docWriter != null) { + val moduleDocWriterList = docWriters.getOrPut(innerModule) { mutableListOf() } + moduleDocWriterList.add(docWriter) + } + writable(getWriter(outerWriter, innerModule)) + } + + /** + * Given a `RustCrate` and a `RustModule.LeafModule()`, it creates a writer to that module and calls the writable. + */ + fun withInlineModuleHierarchyUsingCrate(rustCrate: RustCrate, inlineModule: RustModule.LeafModule, docWriter: DocWriter? = null, writable: Writable) { + val hierarchy = getHierarchy(inlineModule).toMutableList() + check(!hierarchy.first().isInline()) { + "when adding a `RustModule.LeafModule` to the crate, the topmost module in the hierarchy cannot be an inline module" + } + // The last in the hierarchy is the one we will return the writer for. + val bottomMost = hierarchy.removeLast() + + // In case it is a top level module that has been passed (e.g. ModelsModule, OutputsModule) then + // register it with the topLevel writers and call the writable on it. Otherwise, go over the + // complete hierarchy, registering each of the inner modules and then call the `Writable` + // with the bottom most inline module that has been passed. + if (hierarchy.isNotEmpty()) { + val topMost = hierarchy.removeFirst() + + // Create an intermediate writer for all inner modules in the hierarchy + rustCrate.withModule(topMost) { + var writer = this + hierarchy.forEach { + writer = getWriter(writer, it as RustModule.LeafModule) + } + + withInlineModule(writer, bottomMost as RustModule.LeafModule, docWriter, writable) + } + } else { + check(!bottomMost.isInline()) { + "there is only one module in hierarchy so it has to be non-inlined" + } + rustCrate.withModule(bottomMost) { + registerTopMostWriter(this) + writable(this) + } + } + } + + /** + * Given a `Writer` to a module and an inline `RustModule.LeafModule()`, it creates a writer to that module and calls the writable. + * It registers the complete hierarchy including the `outerWriter` if that is not already registrered. + */ + fun withInlineModuleHierarchy(outerWriter: RustWriter, inlineModule: RustModule.LeafModule, docWriter: DocWriter? = null, writable: Writable) { + val hierarchy = getHierarchy(inlineModule).toMutableList() + if (!hierarchy.first().isInline()) { + hierarchy.removeFirst() + } + check(hierarchy.isNotEmpty()) { + "an inline module should always have one parent besides itself" + } + + // The last in the hierarchy is the module under which the new inline module resides. + val bottomMost = hierarchy.removeLast() + + // Create an entry in the HashMap for all the descendent modules in the hierarchy. + var writer = outerWriter + hierarchy.forEach { + writer = getWriter(writer, it as RustModule.LeafModule) + } + + withInlineModule(writer, bottomMost as RustModule.LeafModule, docWriter, writable) + } + + /** + * Returns the complete hierarchy of a `RustModule.LeafModule` from top to bottom + */ + private fun getHierarchy(module: RustModule.LeafModule): List { + var current: RustModule = module + var hierarchy = listOf() + + while (current is RustModule.LeafModule) { + hierarchy = listOf(current as RustModule.LeafModule) + hierarchy + current = current.parent + } + + return hierarchy + } + + + /** + * Writes out each inline module's code (`toString`) to the respective top level `RustWriter`. + */ + fun render() { + fun writeInlineCode(rustWriter: RustWriter, code: String) { + val inlineCode = code.drop(emptyLineCount) + rustWriter.writeWithNoFormatting(inlineCode) + } + + fun renderDescendents(topLevelWriter: RustWriter, inMemoryWriter: RustWriter) { + // Traverse all descendent inline modules and render them. + inlineModuleWriters[inMemoryWriter]?.forEach { + writeDocs(it.inlineModule) + + topLevelWriter.withInlineModule(it.inlineModule) { + writeInlineCode(this, it.writer.toString()) + renderDescendents(this, it.writer) + } + + // Add dependencies introduced by the inline module to the + it.writer.dependencies.forEach { dep -> topLevelWriter.addDependency(dep) } + } + } + + // Go over all the top level modules, create an `inlineModule` on the `RustWriter` + // and call the descendent hierarchy renderer using the `inlineModule::RustWriter` + topLevelModuleWriters.forEach { + val inlineModuleWithWriter = inlineModuleWriters[it] + if (inlineModuleWithWriter != null) { + renderDescendents(it, it) + } + } + } + + /** + * Given the inline-module returns an existing `RustWriter`, or if that inline module + * has never been registered before then a new `RustWriter` is created and returned. + */ + private fun getWriter(outerWriter: RustWriter, inlineModule: RustModule.LeafModule): RustWriter { + // Is this one of our inner writers? + val nestedModuleWriter = inlineModuleWriters[outerWriter] + if (nestedModuleWriter != null) { + return findOrAddToList(nestedModuleWriter, inlineModule) + } + + val inlineWriters = registerTopMostWriter(outerWriter) + return findOrAddToList(inlineWriters, inlineModule) + } + + /** + * Records the root of a dependency graph of inline modules. + */ + private fun registerTopMostWriter(outerWriter: RustWriter) : MutableList { + topLevelModuleWriters.add(outerWriter) + return inlineModuleWriters.getOrPut(outerWriter) { mutableListOf() } + } + + /** + * Either gets a new `RustWriter` for the inline module or creates a new one and adds it to + * the list of inline modules. + */ + private fun findOrAddToList( + inlineModuleList: MutableList, + lookForModule: RustModule.LeafModule + ): RustWriter { + val inlineModule = inlineModuleList.firstOrNull() { + it.inlineModule == lookForModule + } + return if (inlineModule == null) { + val inlineWriter = createNewInlineModule() + inlineModuleList.add(InlineModuleWithWriter(lookForModule, inlineWriter)) + inlineWriter + } else { + inlineModule.writer + } + } + + private fun writeDocs(innerModule: RustModule.LeafModule) { + docWriters[innerModule]?.forEach{ + it() + } + } +} diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustServerCodegenPlugin.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustServerCodegenPlugin.kt index 812bc50916..f63f6977c4 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustServerCodegenPlugin.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustServerCodegenPlugin.kt @@ -67,10 +67,11 @@ class RustServerCodegenPlugin : ServerDecoratableBuildPlugin() { serviceShape: ServiceShape, symbolVisitorConfig: SymbolVisitorConfig, constrainedTypes: Boolean = true, + includeConstrainedShapeProvider: Boolean = true, ) = SymbolVisitor(model, serviceShape = serviceShape, config = symbolVisitorConfig) // Generate public constrained types for directly constrained shapes. - .let { if (constrainedTypes) ConstrainedShapeSymbolProvider(it, model, serviceShape) else it } + .let { if (includeConstrainedShapeProvider) ConstrainedShapeSymbolProvider(it, model, serviceShape, constrainedTypes) else it } // Generate different types for EventStream shapes (e.g. transcribe streaming) .let { EventStreamSymbolProvider(symbolVisitorConfig.runtimeConfig, it, model, CodegenTarget.SERVER) } // Generate [ByteStream] instead of `Blob` for streaming binary shapes (e.g. S3 GetObject) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt index 79572b9c38..f1d1a6bfd6 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt @@ -79,6 +79,7 @@ import software.amazon.smithy.rust.codegen.server.smithy.protocols.ServerProtoco import software.amazon.smithy.rust.codegen.server.smithy.traits.isReachableFromOperationInput import software.amazon.smithy.rust.codegen.server.smithy.transformers.AttachValidationExceptionToConstrainedOperationInputsInAllowList import software.amazon.smithy.rust.codegen.server.smithy.transformers.RecursiveConstraintViolationBoxer +import software.amazon.smithy.rust.codegen.server.smithy.transformers.ConstrainedMemberTransform import software.amazon.smithy.rust.codegen.server.smithy.transformers.RemoveEbsModelValidationException import software.amazon.smithy.rust.codegen.server.smithy.transformers.ShapesReachableFromOperationInputTagger import java.util.logging.Logger @@ -168,6 +169,9 @@ open class ServerCodegenVisitor( .let(RecursiveConstraintViolationBoxer::transform) // Normalize operations by adding synthetic input and output shapes to every operation .let(OperationNormalizer::transform) + // Transforms constrained member shapes into non-constrained member shapes targeting a new shape that + // has the member's constraints. + .let(ConstrainedMemberTransform::transform) // Remove the EBS model's own `ValidationException`, which collides with `smithy.framework#ValidationException` .let(RemoveEbsModelValidationException::transform) // Attach the `smithy.framework#ValidationException` error to operations whose inputs are constrained, @@ -221,9 +225,14 @@ open class ServerCodegenVisitor( } } + rustCrate.initializeInlineModuleWriter(codegenContext.settings.codegenConfig.debugMode) + val serviceShapes = DirectedWalker(model).walkShapes(service) serviceShapes.forEach { it.accept(this) } codegenDecorator.extras(codegenContext, rustCrate) + + rustCrate.getInlineModuleWriter().render() + rustCrate.finalize( settings, model, @@ -278,6 +287,9 @@ open class ServerCodegenVisitor( ).render(CodegenTarget.SERVER) } + // FZ Rebase mine + // StructureGenerator(model, codegenContext.symbolProvider, this, shape).render(CodegenTarget.SERVER) + renderStructureShapeBuilder(shape, this) } } @@ -289,6 +301,9 @@ open class ServerCodegenVisitor( if (codegenContext.settings.codegenConfig.publicConstrainedTypes || shape.isReachableFromOperationInput()) { val serverBuilderGenerator = ServerBuilderGenerator(codegenContext, shape, validationExceptionConversionGenerator) serverBuilderGenerator.render(writer) + // FZ Rebase mine + // val serverBuilderGenerator = ServerBuilderGenerator(codegenContext, shape) + // serverBuilderGenerator.render(rustCrate, writer) if (codegenContext.settings.codegenConfig.publicConstrainedTypes) { writer.implBlock(codegenContext.symbolProvider.toSymbol(shape)) { @@ -307,9 +322,16 @@ open class ServerCodegenVisitor( } if (!codegenContext.settings.codegenConfig.publicConstrainedTypes) { + // FZ Rebase + // val serverBuilderGeneratorWithoutPublicConstrainedTypes = + // ServerBuilderGeneratorWithoutPublicConstrainedTypes(codegenContext, shape, validationExceptionConversionGenerator) + // serverBuilderGeneratorWithoutPublicConstrainedTypes.render(writer) val serverBuilderGeneratorWithoutPublicConstrainedTypes = ServerBuilderGeneratorWithoutPublicConstrainedTypes(codegenContext, shape, validationExceptionConversionGenerator) - serverBuilderGeneratorWithoutPublicConstrainedTypes.render(writer) + serverBuilderGeneratorWithoutPublicConstrainedTypes.render(rustCrate, writer) + // FZ Rebase mine + // ServerBuilderGeneratorWithoutPublicConstrainedTypes(codegenContext, shape) + // serverBuilderGeneratorWithoutPublicConstrainedTypes.render(rustCrate, writer) writer.implBlock(codegenContext.symbolProvider.toSymbol(shape)) { serverBuilderGeneratorWithoutPublicConstrainedTypes.renderConvenienceMethod(this) @@ -330,27 +352,38 @@ open class ServerCodegenVisitor( if (renderUnconstrainedList) { logger.info("[rust-server-codegen] Generating an unconstrained type for collection shape $shape") - rustCrate.withModule(ServerRustModule.UnconstrainedModule) { + // FZ Rebase + // rustCrate.withModule(ServerRustModule.UnconstrainedModule) { + rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.UnconstrainedModule, shape, codegenContext) { UnconstrainedCollectionGenerator( codegenContext, - this, + rustCrate.createInlineModuleCreator(), shape, ).render() } if (!isDirectlyConstrained) { logger.info("[rust-server-codegen] Generating a constrained type for collection shape $shape") - rustCrate.withModule(ServerRustModule.ConstrainedModule) { - PubCrateConstrainedCollectionGenerator(codegenContext, this, shape).render() + // FZ rebase + // rustCrate.withModule(ServerRustModule.ConstrainedModule) { + // PubCrateConstrainedCollectionGenerator(codegenContext, this, shape).render() + + rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.ConstrainedModule, shape, codegenContext) { + PubCrateConstrainedCollectionGenerator(codegenContext, + rustCrate.createInlineModuleCreator(), + shape).render() } } } val constraintsInfo = CollectionTraitInfo.fromShape(shape, codegenContext.constrainedShapeSymbolProvider) if (isDirectlyConstrained) { - rustCrate.withModule(ServerRustModule.Model) { + // FZ rebase + // rustCrate.withModule(ServerRustModule.Model) { + rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.Model, shape, codegenContext) { ConstrainedCollectionGenerator( codegenContext, + // FZ Check? this, shape, constraintsInfo, @@ -360,11 +393,20 @@ open class ServerCodegenVisitor( } if (isDirectlyConstrained || renderUnconstrainedList) { - rustCrate.withModule(ServerRustModule.Model) { + // FZ rebase + // rustCrate.withModule(ServerRustModule.Model) { + // CollectionConstraintViolationGenerator( + // codegenContext, + // this, + // shape, + // constraintsInfo, + // validationExceptionConversionGenerator, + // ).render() + rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.Model, shape, codegenContext) { CollectionConstraintViolationGenerator( codegenContext, - this, - shape, + rustCrate.createInlineModuleCreator(), + shape, constraintsInfo, validationExceptionConversionGenerator, ).render() @@ -382,22 +424,35 @@ open class ServerCodegenVisitor( if (renderUnconstrainedMap) { logger.info("[rust-server-codegen] Generating an unconstrained type for map $shape") - rustCrate.withModule(ServerRustModule.UnconstrainedModule) { - UnconstrainedMapGenerator(codegenContext, this, shape).render() + // FZ rebase + // rustCrate.withModule(ServerRustModule.UnconstrainedModule) { + // UnconstrainedMapGenerator(codegenContext, this, shape).render() + rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.UnconstrainedModule, shape, codegenContext) { + UnconstrainedMapGenerator(codegenContext, + rustCrate.createInlineModuleCreator(), + shape).render() } if (!isDirectlyConstrained) { logger.info("[rust-server-codegen] Generating a constrained type for map $shape") - rustCrate.withModule(ServerRustModule.ConstrainedModule) { - PubCrateConstrainedMapGenerator(codegenContext, this, shape).render() + // FZ rebase + // rustCrate.withModule(ServerRustModule.ConstrainedModule) { + // PubCrateConstrainedMapGenerator(codegenContext, this, shape).render() + rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.ConstrainedModule, shape, codegenContext) { + PubCrateConstrainedMapGenerator(codegenContext, + rustCrate.createInlineModuleCreator(), + shape).render() } } } if (isDirectlyConstrained) { - rustCrate.withModule(ServerRustModule.Model) { + // FZ rebase + // rustCrate.withModule(ServerRustModule.Model) { + rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.Model, shape, codegenContext) { ConstrainedMapGenerator( codegenContext, + // check? this, shape, if (renderUnconstrainedMap) codegenContext.unconstrainedShapeSymbolProvider.toSymbol(shape) else null, @@ -406,10 +461,18 @@ open class ServerCodegenVisitor( } if (isDirectlyConstrained || renderUnconstrainedMap) { - rustCrate.withModule(ServerRustModule.Model) { + // FZ rebase + // rustCrate.withModule(ServerRustModule.Model) { + // MapConstraintViolationGenerator( + // codegenContext, + // this, + // shape, + // validationExceptionConversionGenerator, + // ).render() + rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.Model, shape, codegenContext) { MapConstraintViolationGenerator( codegenContext, - this, + rustCrate.createInlineModuleCreator(), shape, validationExceptionConversionGenerator, ).render() @@ -435,8 +498,14 @@ open class ServerCodegenVisitor( private fun integralShape(shape: NumberShape) { if (shape.isDirectlyConstrained(codegenContext.symbolProvider)) { logger.info("[rust-server-codegen] Generating a constrained integral $shape") - rustCrate.withModule(ServerRustModule.Model) { - ConstrainedNumberGenerator(codegenContext, this, shape, validationExceptionConversionGenerator).render() + // FZ Rebase + // rustCrate.withModule(ServerRustModule.Model) { + rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.Model, shape, codegenContext) { + ConstrainedNumberGenerator(codegenContext, + rustCrate.createInlineModuleCreator(), + shape, + validationExceptionConversionGenerator, + ).render() } } } @@ -447,7 +516,11 @@ open class ServerCodegenVisitor( ) { if (shape.hasTrait()) { logger.info("[rust-server-codegen] Generating an enum $shape") - rustCrate.useShapeWriter(shape) { + // FZ Rebase + // rustCrate.useShapeWriter(shape) { + // enumShapeGeneratorFactory(codegenContext, shape).render(this) + rustCrate.useShapeWriterOrUseWithStructureBuilder(shape, codegenContext) { + // Check this? enumShapeGeneratorFactory(codegenContext, shape).render(this) ConstrainedTraitForEnumGenerator(model, codegenContext.symbolProvider, this, shape).render() } @@ -464,8 +537,15 @@ open class ServerCodegenVisitor( ) } else if (!shape.hasTrait() && shape.isDirectlyConstrained(codegenContext.symbolProvider)) { logger.info("[rust-server-codegen] Generating a constrained string $shape") - rustCrate.withModule(ServerRustModule.Model) { - ConstrainedStringGenerator(codegenContext, this, shape, validationExceptionConversionGenerator).render() + // FZ rebase + // rustCrate.withModule(ServerRustModule.Model) { + // ConstrainedStringGenerator(codegenContext, this, shape, validationExceptionConversionGenerator).render() + rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.Model, shape, codegenContext) { + ConstrainedStringGenerator(codegenContext, + rustCrate.createInlineModuleCreator(), + this, + shape, + validationExceptionConversionGenerator).render() } } } @@ -489,15 +569,23 @@ open class ServerCodegenVisitor( ) ) { logger.info("[rust-server-codegen] Generating an unconstrained type for union shape $shape") - rustCrate.withModule(ServerRustModule.UnconstrainedModule) unconstrainedModuleWriter@{ - rustCrate.withModule(ServerRustModule.Model) modelsModuleWriter@{ - UnconstrainedUnionGenerator( - codegenContext, - this@unconstrainedModuleWriter, - this@modelsModuleWriter, - shape, - ).render() - } + // FZ rebase + // rustCrate.withModule(ServerRustModule.UnconstrainedModule) unconstrainedModuleWriter@{ + // rustCrate.withModule(ServerRustModule.Model) modelsModuleWriter@{ + // UnconstrainedUnionGenerator( + // codegenContext, + // this@unconstrainedModuleWriter, + // this@modelsModuleWriter, + // shape, + // ).render() + // } + rustCrate.withModule(ServerRustModule.UnconstrainedModule) modelsModuleWriter@{ + UnconstrainedUnionGenerator( + codegenContext, + rustCrate.createInlineModuleCreator(), + this@modelsModuleWriter, + shape, + ).render() } } @@ -545,8 +633,16 @@ open class ServerCodegenVisitor( } if (shape.isDirectlyConstrained(codegenContext.symbolProvider)) { - rustCrate.withModule(ServerRustModule.Model) { - ConstrainedBlobGenerator(codegenContext, this, shape, validationExceptionConversionGenerator).render() + // FZ rebase + // rustCrate.withModule(ServerRustModule.Model) { + // ConstrainedBlobGenerator(codegenContext, this, shape, validationExceptionConversionGenerator).render() + rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.Model, shape, codegenContext) { + ConstrainedBlobGenerator(codegenContext, + rustCrate.createInlineModuleCreator(), + this, + shape, + validationExceptionConversionGenerator, + ).render() } } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerSymbolProviders.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerSymbolProviders.kt index 0e368d8517..98ab7364a3 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerSymbolProviders.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerSymbolProviders.kt @@ -28,16 +28,17 @@ class ServerSymbolProviders private constructor( service: ServiceShape, symbolVisitorConfig: SymbolVisitorConfig, publicConstrainedTypes: Boolean, - baseSymbolProviderFactory: (model: Model, service: ServiceShape, symbolVisitorConfig: SymbolVisitorConfig, publicConstrainedTypes: Boolean) -> RustSymbolProvider, + baseSymbolProviderFactory: (model: Model, service: ServiceShape, symbolVisitorConfig: SymbolVisitorConfig, publicConstrainedTypes: Boolean, includeConstraintShapeProvider: Boolean) -> RustSymbolProvider, ): ServerSymbolProviders { - val baseSymbolProvider = baseSymbolProviderFactory(model, service, symbolVisitorConfig, publicConstrainedTypes) + val baseSymbolProvider = baseSymbolProviderFactory(model, service, symbolVisitorConfig, publicConstrainedTypes, publicConstrainedTypes) return ServerSymbolProviders( symbolProvider = baseSymbolProvider, constrainedShapeSymbolProvider = baseSymbolProviderFactory( model, service, symbolVisitorConfig, - true, + publicConstrainedTypes, + true ), unconstrainedShapeSymbolProvider = UnconstrainedShapeSymbolProvider( baseSymbolProviderFactory( @@ -45,6 +46,7 @@ class ServerSymbolProviders private constructor( service, symbolVisitorConfig, false, + false, ), model, publicConstrainedTypes, service, ), diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProvider.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProvider.kt index a134bbb9e9..5c90d13c9a 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProvider.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProvider.kt @@ -21,6 +21,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.RustReservedWords import software.amazon.smithy.rust.codegen.core.rustlang.RustType import software.amazon.smithy.rust.codegen.core.rustlang.Visibility import software.amazon.smithy.rust.codegen.core.smithy.Default +import software.amazon.smithy.rust.codegen.core.smithy.ModelsModule import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.WrappingSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.contextName @@ -100,10 +101,14 @@ class UnconstrainedShapeSymbolProvider( check(shape is CollectionShape || shape is MapShape || shape is UnionShape) val name = unconstrainedTypeNameForCollectionOrMapOrUnionShape(shape) + val parent = shape.getParentAndInlineModuleForConstrainedMember(this, !publicConstrainedTypes)?.second ?: ServerRustModule.UnconstrainedModule + val module = RustModule.new( RustReservedWords.escapeIfNeeded(name.toSnakeCase()), visibility = Visibility.PUBCRATE, - parent = ServerRustModule.UnconstrainedModule, + // FZ rebase + // parent = ServerRustModule.UnconstrainedModule, + parent = parent, inline = true, ) val rustType = RustType.Opaque(name, module.fullyQualifiedPath()) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraints.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraints.kt index 08c7e487b5..fb85601fa7 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraints.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraints.kt @@ -194,18 +194,7 @@ fun validateUnsupportedConstraints( // Traverse the model and error out if: val walker = DirectedWalker(model) - // 1. Constraint traits on member shapes are used. [Constraint trait precedence] has not been implemented yet. - // TODO(https://github.com/awslabs/smithy-rs/issues/1401) - // [Constraint trait precedence]: https://awslabs.github.io/smithy/2.0/spec/model.html#applying-traits - val unsupportedConstraintOnMemberShapeSet = walker - .walkShapes(service) - .asSequence() - .filterIsInstance() - .filterMapShapesToTraits(unsupportedConstraintsOnMemberShapes) - .map { (shape, trait) -> UnsupportedConstraintOnMemberShape(shape as MemberShape, trait) } - .toSet() - - // 2. Constraint traits on streaming blob shapes are used. Their semantics are unclear. + // 1. Constraint traits on streaming blob shapes are used. Their semantics are unclear. // TODO(https://github.com/awslabs/smithy/issues/1389) val unsupportedLengthTraitOnStreamingBlobShapeSet = walker .walkShapes(service) @@ -215,7 +204,7 @@ fun validateUnsupportedConstraints( .map { UnsupportedLengthTraitOnStreamingBlobShape(it, it.expectTrait(), it.expectTrait()) } .toSet() - // 3. Constraint traits in event streams are used. Their semantics are unclear. + // 2. Constraint traits in event streams are used. Their semantics are unclear. // TODO(https://github.com/awslabs/smithy/issues/1388) val eventStreamShapes = walker .walkShapes(service) @@ -236,7 +225,7 @@ fun validateUnsupportedConstraints( val unsupportedConstraintShapeReachableViaAnEventStreamSet = unsupportedConstraintOnNonErrorShapeReachableViaAnEventStreamSet + unsupportedConstraintErrorShapeReachableViaAnEventStreamSet - // 4. Range trait used on unsupported shapes. + // 3. Range trait used on unsupported shapes. // TODO(https://github.com/awslabs/smithy-rs/issues/1401) val unsupportedRangeTraitOnShapeSet = walker .walkShapes(service) @@ -247,7 +236,6 @@ fun validateUnsupportedConstraints( .toSet() val messages = - unsupportedConstraintOnMemberShapeSet.map { it.intoLogMessage(codegenConfig.ignoreUnsupportedConstraints) } + unsupportedLengthTraitOnStreamingBlobShapeSet.map { it.intoLogMessage(codegenConfig.ignoreUnsupportedConstraints) } + unsupportedConstraintShapeReachableViaAnEventStreamSet.map { it.intoLogMessage(codegenConfig.ignoreUnsupportedConstraints) } + unsupportedRangeTraitOnShapeSet.map { it.intoLogMessage(codegenConfig.ignoreUnsupportedConstraints) } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/CollectionConstraintViolationGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/CollectionConstraintViolationGenerator.kt index ef80796d5a..1219b981ae 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/CollectionConstraintViolationGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/CollectionConstraintViolationGenerator.kt @@ -14,6 +14,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.makeRustBoxed import software.amazon.smithy.rust.codegen.core.smithy.module import software.amazon.smithy.rust.codegen.core.util.hasTrait import software.amazon.smithy.rust.codegen.core.util.letIf +import software.amazon.smithy.rust.codegen.server.smithy.InlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.PubCrateConstraintViolationSymbolProvider import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.canReachConstrainedShape @@ -22,7 +23,7 @@ import software.amazon.smithy.rust.codegen.server.smithy.traits.isReachableFromO class CollectionConstraintViolationGenerator( codegenContext: ServerCodegenContext, - private val modelsModuleWriter: RustWriter, + private val inlineModuleCreator: InlineModuleCreator, private val shape: CollectionShape, private val collectionConstraintsInfo: List, private val validationExceptionConversionGenerator: ValidationExceptionConversionGenerator, @@ -47,7 +48,7 @@ class CollectionConstraintViolationGenerator( val isMemberConstrained = targetShape.canReachConstrainedShape(model, symbolProvider) val constraintViolationVisibility = Visibility.publicIf(publicConstrainedTypes, Visibility.PUBCRATE) - modelsModuleWriter.withInlineModule(constraintViolationSymbol.module()) { + inlineModuleCreator(constraintViolationSymbol) { val constraintViolationVariants = constraintsInfo.map { it.constraintViolationVariant }.toMutableList() if (isMemberConstrained) { constraintViolationVariants += { diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGenerator.kt index 1215691787..455a000470 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGenerator.kt @@ -24,6 +24,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.makeMaybeConstrained import software.amazon.smithy.rust.codegen.core.smithy.module import software.amazon.smithy.rust.codegen.core.smithy.rustType import software.amazon.smithy.rust.codegen.core.util.orNull +import software.amazon.smithy.rust.codegen.server.smithy.InlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.PubCrateConstraintViolationSymbolProvider import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.traits.isReachableFromOperationInput @@ -31,6 +32,7 @@ import software.amazon.smithy.rust.codegen.server.smithy.validationErrorMessage class ConstrainedBlobGenerator( val codegenContext: ServerCodegenContext, + private val inlineModuleCreator : InlineModuleCreator, val writer: RustWriter, val shape: BlobShape, private val validationExceptionConversionGenerator: ValidationExceptionConversionGenerator, @@ -110,7 +112,7 @@ class ConstrainedBlobGenerator( "From" to RuntimeType.From, ) - writer.withInlineModule(constraintViolation.module()) { + inlineModuleCreator(constraintViolation) { renderConstraintViolationEnum(this, shape, constraintViolation) } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGenerator.kt index 6680d154e9..61e7aed6a5 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGenerator.kt @@ -29,6 +29,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.module import software.amazon.smithy.rust.codegen.core.util.UNREACHABLE import software.amazon.smithy.rust.codegen.core.util.expectTrait import software.amazon.smithy.rust.codegen.core.util.redactIfNecessary +import software.amazon.smithy.rust.codegen.server.smithy.InlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.PubCrateConstraintViolationSymbolProvider import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.traits.isReachableFromOperationInput @@ -41,7 +42,8 @@ import software.amazon.smithy.rust.codegen.server.smithy.validationErrorMessage */ class ConstrainedNumberGenerator( val codegenContext: ServerCodegenContext, - val writer: RustWriter, + private val inlineModuleCreator: InlineModuleCreator, + private val writer: RustWriter, val shape: NumberShape, private val validationExceptionConversionGenerator: ValidationExceptionConversionGenerator, ) { @@ -132,7 +134,7 @@ class ConstrainedNumberGenerator( writer.renderTryFrom(unconstrainedTypeName, name, constraintViolation, constraintsInfo) - writer.withInlineModule(constraintViolation.module()) { + inlineModuleCreator(constraintViolation) { rust( """ ##[derive(Debug, PartialEq)] diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGenerator.kt index 73a2ac7a0d..7d3fe75110 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGenerator.kt @@ -27,13 +27,13 @@ import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.expectRustMetadata import software.amazon.smithy.rust.codegen.core.smithy.makeMaybeConstrained -import software.amazon.smithy.rust.codegen.core.smithy.module import software.amazon.smithy.rust.codegen.core.smithy.testModuleForShape import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.PANIC import software.amazon.smithy.rust.codegen.core.util.hasTrait import software.amazon.smithy.rust.codegen.core.util.orNull import software.amazon.smithy.rust.codegen.core.util.redactIfNecessary +import software.amazon.smithy.rust.codegen.server.smithy.InlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.PubCrateConstraintViolationSymbolProvider import software.amazon.smithy.rust.codegen.server.smithy.ServerCargoDependency import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext @@ -48,7 +48,8 @@ import software.amazon.smithy.rust.codegen.server.smithy.validationErrorMessage */ class ConstrainedStringGenerator( val codegenContext: ServerCodegenContext, - val writer: RustWriter, + private val inlineModuleCreator: InlineModuleCreator, + private val writer: RustWriter, val shape: StringShape, private val validationExceptionConversionGenerator: ValidationExceptionConversionGenerator, ) { @@ -139,7 +140,7 @@ class ConstrainedStringGenerator( "From" to RuntimeType.From, ) - writer.withInlineModule(constraintViolation.module()) { + inlineModuleCreator(constraintViolation) { renderConstraintViolationEnum(this, shape, constraintViolation) } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/MapConstraintViolationGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/MapConstraintViolationGenerator.kt index 8bbf95ed88..51c156d0f3 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/MapConstraintViolationGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/MapConstraintViolationGenerator.kt @@ -15,6 +15,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.makeRustBoxed import software.amazon.smithy.rust.codegen.core.smithy.module import software.amazon.smithy.rust.codegen.core.util.hasTrait import software.amazon.smithy.rust.codegen.core.util.letIf +import software.amazon.smithy.rust.codegen.server.smithy.InlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.PubCrateConstraintViolationSymbolProvider import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.traits.ConstraintViolationRustBoxTrait @@ -22,7 +23,7 @@ import software.amazon.smithy.rust.codegen.server.smithy.traits.isReachableFromO class MapConstraintViolationGenerator( codegenContext: ServerCodegenContext, - private val modelsModuleWriter: RustWriter, + private val inlineModuleCreator: InlineModuleCreator, val shape: MapShape, private val validationExceptionConversionGenerator: ValidationExceptionConversionGenerator, ) { @@ -67,7 +68,8 @@ class MapConstraintViolationGenerator( } else { Visibility.PUBCRATE } - modelsModuleWriter.withInlineModule(constraintViolationSymbol.module()) { + + inlineModuleCreator(constraintViolationSymbol) { // TODO(https://github.com/awslabs/smithy-rs/issues/1401) We should really have two `ConstraintViolation` // types here. One will just have variants for each constraint trait on the map shape, for use by the user. // The other one will have variants if the shape's key or value is directly or transitively constrained, diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/PubCrateConstrainedCollectionGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/PubCrateConstrainedCollectionGenerator.kt index 09f9352cde..647c99273b 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/PubCrateConstrainedCollectionGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/PubCrateConstrainedCollectionGenerator.kt @@ -17,6 +17,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.withBlock import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.isOptional import software.amazon.smithy.rust.codegen.core.smithy.module +import software.amazon.smithy.rust.codegen.server.smithy.InlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.canReachConstrainedShape import software.amazon.smithy.rust.codegen.server.smithy.isDirectlyConstrained @@ -41,7 +42,7 @@ import software.amazon.smithy.rust.codegen.server.smithy.typeNameContainsNonPubl */ class PubCrateConstrainedCollectionGenerator( val codegenContext: ServerCodegenContext, - val writer: RustWriter, + private val inlineModuleCreator: InlineModuleCreator, val shape: CollectionShape, ) { private val model = codegenContext.model @@ -74,7 +75,7 @@ class PubCrateConstrainedCollectionGenerator( "From" to RuntimeType.From, ) - writer.withInlineModule(constrainedSymbol.module()) { + inlineModuleCreator(constrainedSymbol) { rustTemplate( """ ##[derive(Debug, Clone)] diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/PubCrateConstrainedMapGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/PubCrateConstrainedMapGenerator.kt index 9d5ad81125..9e8308dc8b 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/PubCrateConstrainedMapGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/PubCrateConstrainedMapGenerator.kt @@ -18,6 +18,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.withBlock import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.isOptional import software.amazon.smithy.rust.codegen.core.smithy.module +import software.amazon.smithy.rust.codegen.server.smithy.InlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.canReachConstrainedShape import software.amazon.smithy.rust.codegen.server.smithy.isDirectlyConstrained @@ -40,7 +41,7 @@ import software.amazon.smithy.rust.codegen.server.smithy.typeNameContainsNonPubl */ class PubCrateConstrainedMapGenerator( val codegenContext: ServerCodegenContext, - val writer: RustWriter, + private val inlineModuleCreator: InlineModuleCreator, val shape: MapShape, ) { private val model = codegenContext.model @@ -75,7 +76,7 @@ class PubCrateConstrainedMapGenerator( "From" to RuntimeType.From, ) - writer.withInlineModule(constrainedSymbol.module()) { + inlineModuleCreator(constrainedSymbol) { rustTemplate( """ ##[derive(Debug, Clone)] diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGenerator.kt index 3d65e4c89e..3a36be1861 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGenerator.kt @@ -29,6 +29,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.stripOuter import software.amazon.smithy.rust.codegen.core.rustlang.withBlock import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RustCrate import software.amazon.smithy.rust.codegen.core.smithy.expectRustMetadata import software.amazon.smithy.rust.codegen.core.smithy.isOptional import software.amazon.smithy.rust.codegen.core.smithy.isRustBoxed @@ -51,6 +52,7 @@ import software.amazon.smithy.rust.codegen.server.smithy.hasConstraintTraitOrTar import software.amazon.smithy.rust.codegen.server.smithy.targetCanReachConstrainedShape import software.amazon.smithy.rust.codegen.server.smithy.traits.ConstraintViolationRustBoxTrait import software.amazon.smithy.rust.codegen.server.smithy.traits.isReachableFromOperationInput +import software.amazon.smithy.rust.codegen.server.smithy.withInMemoryInlineModule import software.amazon.smithy.rust.codegen.server.smithy.wouldHaveConstrainedWrapperTupleTypeWerePublicConstrainedTypesEnabled /** @@ -87,7 +89,7 @@ import software.amazon.smithy.rust.codegen.server.smithy.wouldHaveConstrainedWra * [derive_builder]: https://docs.rs/derive_builder/latest/derive_builder/index.html */ class ServerBuilderGenerator( - codegenContext: ServerCodegenContext, + val codegenContext: ServerCodegenContext, private val shape: StructureShape, private val customValidationExceptionWithReasonConversionGenerator: ValidationExceptionConversionGenerator, ) { @@ -153,9 +155,9 @@ class ServerBuilderGenerator( "MaybeConstrained" to RuntimeType.MaybeConstrained, ) - fun render(writer: RustWriter) { - writer.docs("See #D.", structureSymbol) - writer.withInlineModule(builderSymbol.module()) { + fun render(rustCrate : RustCrate, writer: RustWriter) { + val docWriter : () -> Unit = { writer.docs("See #D.", structureSymbol) } + rustCrate.withInMemoryInlineModule(writer, builderSymbol.module(), docWriter) { renderBuilder(this) } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorWithoutPublicConstrainedTypes.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorWithoutPublicConstrainedTypes.kt index 32e58fd44e..2ae17d1a80 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorWithoutPublicConstrainedTypes.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorWithoutPublicConstrainedTypes.kt @@ -23,12 +23,14 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rustBlockTemplate import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.withBlock import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RustCrate import software.amazon.smithy.rust.codegen.core.smithy.expectRustMetadata import software.amazon.smithy.rust.codegen.core.smithy.isOptional import software.amazon.smithy.rust.codegen.core.smithy.makeOptional import software.amazon.smithy.rust.codegen.core.smithy.module import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.ServerRuntimeType +import software.amazon.smithy.rust.codegen.server.smithy.withInMemoryInlineModule /** * Generates a builder for the Rust type associated with the [StructureShape]. @@ -90,12 +92,12 @@ class ServerBuilderGeneratorWithoutPublicConstrainedTypes( "MaybeConstrained" to RuntimeType.MaybeConstrained, ) - fun render(writer: RustWriter) { + fun render(rustCrate: RustCrate, writer: RustWriter) { check(!codegenContext.settings.codegenConfig.publicConstrainedTypes) { "ServerBuilderGeneratorWithoutPublicConstrainedTypes should only be used when `publicConstrainedTypes` is false" } - writer.docs("See #D.", structureSymbol) - writer.withInlineModule(builderSymbol.module()) { + val docWriter = { writer.docs("See #D.", structureSymbol) } + rustCrate.withInMemoryInlineModule(writer, builderSymbol.module(), docWriter) { renderBuilder(this) } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderSymbol.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderSymbol.kt index 9720717383..a605009ddf 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderSymbol.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderSymbol.kt @@ -2,7 +2,6 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0 */ - package software.amazon.smithy.rust.codegen.server.smithy.generators import software.amazon.smithy.codegen.core.Symbol @@ -23,7 +22,7 @@ fun StructureShape.serverBuilderSymbol(codegenContext: ServerCodegenContext): Sy !codegenContext.settings.codegenConfig.publicConstrainedTypes, ) -fun StructureShape.serverBuilderSymbol(symbolProvider: SymbolProvider, pubCrate: Boolean): Symbol { +fun StructureShape.serverBuilderModule(symbolProvider: SymbolProvider, pubCrate: Boolean): RustModule.LeafModule { val structureSymbol = symbolProvider.toSymbol(this) val builderNamespace = RustReservedWords.escapeIfNeeded(structureSymbol.name.toSnakeCase()) + if (pubCrate) { @@ -35,7 +34,11 @@ fun StructureShape.serverBuilderSymbol(symbolProvider: SymbolProvider, pubCrate: true -> Visibility.PUBCRATE false -> Visibility.PUBLIC } - val builderModule = RustModule.new(builderNamespace, visibility, parent = structureSymbol.module(), inline = true) + return RustModule.new(builderNamespace, visibility, parent = structureSymbol.module(), inline = true) +} + +fun StructureShape.serverBuilderSymbol(symbolProvider: SymbolProvider, pubCrate: Boolean): Symbol { + val builderModule = serverBuilderModule(symbolProvider, pubCrate) val rustType = RustType.Opaque("Builder", builderModule.fullyQualifiedPath()) return Symbol.builder() .rustType(rustType) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGenerator.kt index 3d233d28ef..eb5c06b561 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGenerator.kt @@ -20,6 +20,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.isOptional import software.amazon.smithy.rust.codegen.core.smithy.makeMaybeConstrained import software.amazon.smithy.rust.codegen.core.smithy.module import software.amazon.smithy.rust.codegen.core.util.hasTrait +import software.amazon.smithy.rust.codegen.server.smithy.InlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.PubCrateConstraintViolationSymbolProvider import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.UnconstrainedShapeSymbolProvider @@ -40,7 +41,7 @@ import software.amazon.smithy.rust.codegen.server.smithy.traits.ConstraintViolat */ class UnconstrainedCollectionGenerator( val codegenContext: ServerCodegenContext, - private val unconstrainedModuleWriter: RustWriter, + private val inlineModuleCreator: InlineModuleCreator, val shape: CollectionShape, ) { private val model = codegenContext.model @@ -72,7 +73,7 @@ class UnconstrainedCollectionGenerator( val innerMemberSymbol = unconstrainedShapeSymbolProvider.toSymbol(shape.member) - unconstrainedModuleWriter.withInlineModule(symbol.module()) { + inlineModuleCreator(symbol) { rustTemplate( """ ##[derive(Debug, Clone)] diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGenerator.kt index b6445da017..9f1c2c6d39 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGenerator.kt @@ -21,6 +21,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.isOptional import software.amazon.smithy.rust.codegen.core.smithy.makeMaybeConstrained import software.amazon.smithy.rust.codegen.core.smithy.module import software.amazon.smithy.rust.codegen.core.util.hasTrait +import software.amazon.smithy.rust.codegen.server.smithy.InlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.PubCrateConstraintViolationSymbolProvider import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.canReachConstrainedShape @@ -40,7 +41,7 @@ import software.amazon.smithy.rust.codegen.server.smithy.traits.ConstraintViolat */ class UnconstrainedMapGenerator( val codegenContext: ServerCodegenContext, - private val unconstrainedModuleWriter: RustWriter, + private val inlineModuleCreator: InlineModuleCreator, val shape: MapShape, ) { private val model = codegenContext.model @@ -74,7 +75,7 @@ class UnconstrainedMapGenerator( val keySymbol = unconstrainedShapeSymbolProvider.toSymbol(keyShape) val valueMemberSymbol = unconstrainedShapeSymbolProvider.toSymbol(shape.value) - unconstrainedModuleWriter.withInlineModule(symbol.module()) { + inlineModuleCreator(symbol) { rustTemplate( """ ##[derive(Debug, Clone)] diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGenerator.kt index dac275e051..6b7b1ff911 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGenerator.kt @@ -23,11 +23,11 @@ import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.makeMaybeConstrained import software.amazon.smithy.rust.codegen.core.smithy.makeRustBoxed -import software.amazon.smithy.rust.codegen.core.smithy.module import software.amazon.smithy.rust.codegen.core.smithy.traits.RustBoxTrait import software.amazon.smithy.rust.codegen.core.util.hasTrait import software.amazon.smithy.rust.codegen.core.util.letIf import software.amazon.smithy.rust.codegen.core.util.toPascalCase +import software.amazon.smithy.rust.codegen.server.smithy.InlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.PubCrateConstraintViolationSymbolProvider import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.canReachConstrainedShape @@ -49,7 +49,7 @@ import software.amazon.smithy.rust.codegen.server.smithy.traits.isReachableFromO */ class UnconstrainedUnionGenerator( val codegenContext: ServerCodegenContext, - private val unconstrainedModuleWriter: RustWriter, + private val inlineModuleCreator: InlineModuleCreator, private val modelsModuleWriter: RustWriter, val shape: UnionShape, ) { @@ -77,7 +77,7 @@ class UnconstrainedUnionGenerator( val constraintViolationSymbol = constraintViolationSymbolProvider.toSymbol(shape) val constraintViolationName = constraintViolationSymbol.name - unconstrainedModuleWriter.withInlineModule(symbol.module()) { + inlineModuleCreator(symbol) { rustBlock( """ ##[allow(clippy::enum_variant_names)] @@ -133,8 +133,10 @@ class UnconstrainedUnionGenerator( } else { Visibility.PUBCRATE } - modelsModuleWriter.withInlineModule( - constraintViolationSymbol.module(), + + inlineModuleCreator( + //constraintViolationSymbol.module(), codegenContext + constraintViolationSymbol ) { Attribute(derive(RuntimeType.Debug, RuntimeType.PartialEq)).render(this) rustBlock("pub${if (constraintViolationVisibility == Visibility.PUBCRATE) " (crate)" else ""} enum $constraintViolationName") { diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocolTestGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocolTestGenerator.kt index 89c82808a7..28480bbc5a 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocolTestGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocolTestGenerator.kt @@ -779,80 +779,11 @@ class ServerProtocolTestGenerator( FailingTest(RestJsonValidation, "RestJsonMalformedRangeMaxFloat", TestType.MalformedRequest), FailingTest(RestJsonValidation, "RestJsonMalformedRangeMinFloat", TestType.MalformedRequest), - // See https://github.com/awslabs/smithy-rs/issues/1969 - FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeShortOverride_case0", TestType.MalformedRequest), - FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeShortOverride_case1", TestType.MalformedRequest), - FailingTest( - MalformedRangeValidation, - "RestJsonMalformedRangeIntegerOverride_case0", - TestType.MalformedRequest, - ), - FailingTest( - MalformedRangeValidation, - "RestJsonMalformedRangeIntegerOverride_case1", - TestType.MalformedRequest, - ), - FailingTest( - MalformedRangeValidation, - "RestJsonMalformedRangeLongOverride_case0", - TestType.MalformedRequest, - ), - FailingTest( - MalformedRangeValidation, - "RestJsonMalformedRangeLongOverride_case1", - TestType.MalformedRequest, - ), - FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeMaxShortOverride", TestType.MalformedRequest), - FailingTest( - MalformedRangeValidation, - "RestJsonMalformedRangeMaxIntegerOverride", - TestType.MalformedRequest, - ), - FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeMaxLongOverride", TestType.MalformedRequest), - FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeMinShortOverride", TestType.MalformedRequest), - FailingTest( - MalformedRangeValidation, - "RestJsonMalformedRangeMinIntegerOverride", - TestType.MalformedRequest, - ), - FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeMinLongOverride", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedRangeByteOverride_case0", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedRangeByteOverride_case1", TestType.MalformedRequest), + // Tests involving floating point shapes and the `@range` trait; see https://github.com/awslabs/smithy-rs/issues/2007 FailingTest(RestJsonValidation, "RestJsonMalformedRangeFloatOverride_case0", TestType.MalformedRequest), FailingTest(RestJsonValidation, "RestJsonMalformedRangeFloatOverride_case1", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedLengthMaxStringOverride", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedLengthMinStringOverride", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedRangeMaxByteOverride", TestType.MalformedRequest), FailingTest(RestJsonValidation, "RestJsonMalformedRangeMaxFloatOverride", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedRangeMinByteOverride", TestType.MalformedRequest), FailingTest(RestJsonValidation, "RestJsonMalformedRangeMinFloatOverride", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedPatternListOverride_case0", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedPatternListOverride_case1", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedPatternMapKeyOverride_case0", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedPatternMapKeyOverride_case1", TestType.MalformedRequest), - FailingTest( - RestJsonValidation, - "RestJsonMalformedPatternMapValueOverride_case0", - TestType.MalformedRequest, - ), - FailingTest( - RestJsonValidation, - "RestJsonMalformedPatternMapValueOverride_case1", - TestType.MalformedRequest, - ), - FailingTest(RestJsonValidation, "RestJsonMalformedPatternStringOverride_case0", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedPatternStringOverride_case1", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedPatternUnionOverride_case0", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedPatternUnionOverride_case1", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedLengthBlobOverride_case0", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedLengthBlobOverride_case1", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedLengthListOverride_case0", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedLengthListOverride_case1", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedLengthMapOverride_case0", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedLengthMapOverride_case1", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedLengthStringOverride_case0", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedLengthStringOverride_case1", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedLengthStringOverride_case2", TestType.MalformedRequest), // Some tests for the S3 service (restXml). FailingTest("com.amazonaws.s3#AmazonS3", "GetBucketLocationUnwrappedOutput", TestType.Response), diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt index 69f75f46b5..6b113ddda4 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt @@ -14,6 +14,7 @@ import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.implBlock import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig +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.SymbolVisitorConfig import software.amazon.smithy.rust.codegen.core.smithy.generators.StructureGenerator @@ -26,6 +27,7 @@ import software.amazon.smithy.rust.codegen.server.smithy.ServerRustSettings import software.amazon.smithy.rust.codegen.server.smithy.ServerSymbolProviders import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.generators.ServerBuilderGenerator +import software.amazon.smithy.rust.codegen.server.smithy.getInlineModuleWriter // These are the settings we default to if the user does not override them in their `smithy-build.json`. val ServerTestSymbolVisitorConfig = SymbolVisitorConfig( @@ -125,8 +127,13 @@ fun StructureShape.serverRenderWithModelBuilder(model: Model, symbolProvider: Ru // Note that this always uses `ServerBuilderGenerator` and _not_ `ServerBuilderGeneratorWithoutPublicConstrainedTypes`, // regardless of the `publicConstrainedTypes` setting. val modelBuilder = ServerBuilderGenerator(serverCodegenContext, this, SmithyValidationExceptionConversionGenerator(serverCodegenContext)) - modelBuilder.render(writer) + modelBuilder.render(rustCrate, writer) writer.implBlock(symbolProvider.toSymbol(this)) { + // FZ Rebase mine + // val modelBuilder = ServerBuilderGenerator(serverCodegenContext, this) + // modelBuilder.render(rustCrate, writer) + // writer.implBlock(this, symbolProvider) { modelBuilder.renderConvenienceMethod(this) } + rustCrate.getInlineModuleWriter().render() } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/traits/SyntheticStructureFromConstrainedMemberTrait.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/traits/SyntheticStructureFromConstrainedMemberTrait.kt new file mode 100644 index 0000000000..0bc2010b75 --- /dev/null +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/traits/SyntheticStructureFromConstrainedMemberTrait.kt @@ -0,0 +1,16 @@ +package software.amazon.smithy.rust.codegen.server.smithy.traits + +import software.amazon.smithy.model.node.Node +import software.amazon.smithy.model.shapes.MemberShape +import software.amazon.smithy.model.shapes.Shape +import software.amazon.smithy.model.shapes.ShapeId +import software.amazon.smithy.model.traits.AnnotationTrait + +/** + * Trait applied to an overridden shape indicating the member of this new shape type + */ +class SyntheticStructureFromConstrainedMemberTrait(val container : Shape, val member: MemberShape): AnnotationTrait(SyntheticStructureFromConstrainedMemberTrait.ID, Node.objectNode()) { + companion object { + val ID : ShapeId = ShapeId.from("smithy.api.internal#overriddenMember") + } +} diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/transformers/ConstrainedMemberTransform.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/transformers/ConstrainedMemberTransform.kt new file mode 100644 index 0000000000..1ae50a06ac --- /dev/null +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/transformers/ConstrainedMemberTransform.kt @@ -0,0 +1,222 @@ +package software.amazon.smithy.rust.codegen.server.smithy.transformers + +import software.amazon.smithy.model.Model +import software.amazon.smithy.model.shapes.AbstractShapeBuilder +import software.amazon.smithy.model.shapes.ListShape +import software.amazon.smithy.model.shapes.MapShape +import software.amazon.smithy.model.shapes.MemberShape +import software.amazon.smithy.model.shapes.Shape +import software.amazon.smithy.model.shapes.ShapeId +import software.amazon.smithy.model.shapes.StructureShape +import software.amazon.smithy.model.shapes.UnionShape +import software.amazon.smithy.model.traits.RequiredTrait +import software.amazon.smithy.model.traits.Trait +import software.amazon.smithy.model.transform.ModelTransformer +import software.amazon.smithy.rust.codegen.core.smithy.DirectedWalker +import software.amazon.smithy.rust.codegen.core.smithy.traits.SyntheticInputTrait +import software.amazon.smithy.rust.codegen.core.smithy.traits.SyntheticOutputTrait +import software.amazon.smithy.rust.codegen.server.smithy.traits.SyntheticStructureFromConstrainedMemberTrait +import software.amazon.smithy.utils.ToSmithyBuilder +import java.lang.IllegalStateException +import java.util.* +import software.amazon.smithy.rust.codegen.core.util.UNREACHABLE +import software.amazon.smithy.rust.codegen.core.util.orNull +import software.amazon.smithy.rust.codegen.server.smithy.allConstraintTraits +import software.amazon.smithy.rust.codegen.server.smithy.transformers.ConstrainedMemberTransform.makeNonConstrained + +/** + * Transforms all member shapes that have constraints on them into equivalent non-constrained + * member shapes targeting synthetic constrained structure shapes with the member's constraints. + * + * E.g.: + * ``` + * structure A { + * @length(min: 1, max: 69) + * string: ConstrainedString + * } + * + * @length(min: 2, max: 10) + * @pattern("^[A-Za-z]+$") + * string ConstrainedString + * ``` + * + * to + * + * ``` + * structure A { + * string: OverriddenConstrainedString + * } + * + * @length(min: 1, max: 69) + * @pattern("^[A-Za-z]+$") + * OverriddenConstrainedString + * + * @length(min: 2, max: 10) + * @pattern("^[A-Za-z]+$") + * string ConstrainedString + * ``` + */ +object ConstrainedMemberTransform { + private data class MemberShapeTransformation( + val newShape: Shape, + val memberToChange: MemberShape, + val traitsToKeep: List, + ) + + private val memberConstraintTraitsToOverride = allConstraintTraits - RequiredTrait::class.java + + private fun Shape.hasMemberConstraintTrait() = + memberConstraintTraitsToOverride.any(this::hasTrait) + + fun transform(model: Model): Model { + val additionalNames = HashSet() + val walker = DirectedWalker(model) + + // Find all synthetic input / output structures that have been added by + // the OperationNormalizer, get constrained members out of those structures, + // convert them into non-constrained members and then pass them to the transformer. + // The transformer will add new shapes, and will replace existing member shapes' target + // with the newly added shapes. + val transformations = model.operationShapes + .flatMap { listOfNotNull(it.input.orNull(), it.output.orNull()) } + .mapNotNull { model.expectShape(it).asStructureShape().orElse(null) } + .filter { it.hasTrait(SyntheticInputTrait.ID) || it.hasTrait(SyntheticOutputTrait.ID) } + .flatMap { walker.walkShapes(it) } + .filter { it is StructureShape || it is ListShape || it is UnionShape || it is MapShape } + .flatMap { it.constrainedMembers() } + .mapNotNull { + val transformation = it.makeNonConstrained(model, additionalNames) + if (transformation != null) { + // Keep record of new names that have been generated to ensure none of them regenerated. + additionalNames.add(transformation.newShape.id) + } + + transformation + } + + return applyTransformations(model, transformations) + } + + /*** + * Returns a Model that has all the transformations applied on the original model. + */ + private fun applyTransformations( + model: Model, + transformations: List, + ): Model { + val modelBuilder = model.toBuilder() + + val memberShapesToReplace = transformations.map { + // Add the new shape to the model. + modelBuilder.addShape(it.newShape) + + it.memberToChange.toBuilder() + .target(it.newShape.id) + .traits(it.traitsToKeep) + .build() + } + + // Change all original constrained member shapes with the new standalone shapes. + return ModelTransformer.create() + .replaceShapes(modelBuilder.build(), memberShapesToReplace) + } + + /** + * Returns a list of members that have constraint traits applied to them + */ + private fun Shape.constrainedMembers(): List = + this.allMembers.values.filter { + it.hasMemberConstraintTrait() + } + + /** + * Returns the unique (within the model) shape ID of the new shape + */ + private fun overriddenShapeId( + model: Model, + additionalNames: Set, + memberShape: ShapeId, + ): ShapeId { + val structName = memberShape.name + val memberName = memberShape.member.orElse(null) + .replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() } + + fun makeStructName(suffix: String = "") = + ShapeId.from("${memberShape.namespace}#${structName}${memberName}$suffix") + + fun structNameIsUnique(newName: ShapeId) = + model.getShape(newName).isEmpty && !additionalNames.contains(newName) + + fun generateUniqueName(): ShapeId { + // Ensure the name does not already exist in the model, else make it unique + // by appending a new number as the suffix. + (0..100).forEach { + val extractedStructName = if (it == 0) makeStructName("") else makeStructName("$it") + if (structNameIsUnique(extractedStructName)) + return extractedStructName + } + + throw IllegalStateException("A unique name for the overridden structure type could not be generated") + } + + return generateUniqueName() + } + + /** + * Returns the transformation that would be required to turn the given member shape + * into a non-constrained member shape. + */ + private fun MemberShape.makeNonConstrained( + model: Model, + additionalNames: MutableSet, + ): MemberShapeTransformation? { + val (constraintTraits, otherTraits) = this.allTraits.values + .partition { + memberConstraintTraitsToOverride.contains(it.javaClass) + } + + // No transformation required in case the member shape has no constraints. + if (constraintTraits.isEmpty()) + return null + + // Build a new shape similar to the target of the constrained member shape. It should + // have all of the original constraints that have not been overridden, and the ones + // that this member shape overrides. + val targetShape = model.expectShape(this.target) + if (targetShape !is ToSmithyBuilder<*>) + UNREACHABLE("member target shapes will always be buildable") + + return when (val builder = targetShape.toBuilder()) { + is AbstractShapeBuilder<*, *> -> { + // Use the target builder to create a new standalone shape that would + // be added to the model later on. Keep all existing traits on the target + // but replace the ones that are overridden on the member shape. + val nonOverriddenTraitsOnTarget = + builder.allTraits.values.filter { existingTrait -> + constraintTraits.none { it.toShapeId() == existingTrait.toShapeId() } + } + + // Add a synthetic constraint on all new shapes being defined, that would link + // the new shape to the root structure from which it is reachable. + val syntheticTrait = + SyntheticStructureFromConstrainedMemberTrait(model.expectShape(this.container), this) + + // Combine target traits, overridden traits and the synthetic trait + val newTraits = + nonOverriddenTraitsOnTarget + constraintTraits + syntheticTrait + + // Create a new unique standalone shape that will be added to the model later on + val shapeId = overriddenShapeId(model, additionalNames, this.id) + val standaloneShape = builder.id(shapeId) + .traits(newTraits) + .build() + + // Since the new shape has not been added to the model as yet, the current + // memberShape's target cannot be changed to the new shape. + MemberShapeTransformation(standaloneShape, this, otherTraits) + } + + else -> UNREACHABLE("Constraint traits cannot to applied on ${this.id}") + } + } +} diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt new file mode 100644 index 0000000000..d2967ebc00 --- /dev/null +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt @@ -0,0 +1,468 @@ +package software.amazon.smithy.rust.codegen.server.smithy + +import org.junit.jupiter.api.Test +import software.amazon.smithy.model.Model +import software.amazon.smithy.model.shapes.ShapeId +import software.amazon.smithy.model.traits.RequiredTrait +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.smithy.DirectedWalker +import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel +import software.amazon.smithy.rust.codegen.server.smithy.transformers.ConstrainedMemberTransform +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeCrateLocation +import software.amazon.smithy.rust.codegen.core.smithy.RustCrate +import software.amazon.smithy.rust.codegen.core.smithy.transformers.OperationNormalizer +import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace +import software.amazon.smithy.rust.codegen.core.testutil.generatePluginContext +import software.amazon.smithy.rust.codegen.core.testutil.unitTest +import software.amazon.smithy.rust.codegen.core.util.runCommand +import software.amazon.smithy.rust.codegen.core.util.toPascalCase +import software.amazon.smithy.rust.codegen.core.util.toSnakeCase +import software.amazon.smithy.rust.codegen.server.smithy.customize.CombinedServerCodegenDecorator +import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext +import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestSymbolProvider +import java.io.File +import java.nio.file.Path + +class ConstraintsMemberShapeTest { + private val outputModelOnly = """ + namespace constrainedMemberShape + + use aws.protocols#restJson1 + use aws.api#data + + @restJson1 + service ConstrainedService { + operations: [OperationUsingGet] + } + + @http(uri: "/anOperation", method: "GET") + operation OperationUsingGet { + output : OperationUsingGetOutput + } + structure OperationUsingGetOutput { + plainLong : Long + plainInteger : Integer + plainShort : Short + plainByte : Byte + plainFloat: Float + plainString: String + + @range(min: 1, max:100) + constrainedLong : Long + @range(min: 2, max:100) + constrainedInteger : Integer + @range(min: 3, max:100) + constrainedShort : Short + @range(min: 4, max:100) + constrainedByte : Byte + @length(max: 100) + constrainedString: String + + @required + @range(min: 5, max:100) + requiredConstrainedLong : Long + @required + @range(min: 6, max:100) + requiredConstrainedInteger : Integer + @required + @range(min: 7, max:100) + requiredConstrainedShort : Short + @required + @range(min: 8, max:100) + requiredConstrainedByte : Byte + @required + @length(max: 101) + requiredConstrainedString: String + + patternString : PatternString + + @data("content") + @pattern("^[g-m]+${'$'}") + constrainedPatternString : PatternString + + plainStringList : PlainStringList + patternStringList : PatternStringList + patternStringListOverride : PatternStringListOverride + + plainStructField : PlainStructWithInteger + structWithConstrainedMember : StructWithConstrainedMember + structWithConstrainedMemberOverride : StructWithConstrainedMemberOverride + + patternUnion: PatternUnion + patternUnionOverride: PatternUnionOverride + patternMap : PatternMap + patternMapOverride: PatternMapOverride + } + list ListWithIntegerMemberStruct { + member: PlainStructWithInteger + } + structure PlainStructWithInteger { + lat : Integer + long : Integer + } + structure StructWithConstrainedMember { + @range(min: 100) + lat : Integer + long : Integer + } + structure StructWithConstrainedMemberOverride { + @range(min: 10) + lat : RangedInteger + @range(min: 10, max:100) + long : RangedInteger + } + list PlainStringList { + member: String + } + list PatternStringList { + member: PatternString + } + list PatternStringListOverride { + @pattern("^[g-m]+${'$'}") + member: PatternString + } + map PatternMap { + key: PatternString, + value: PatternString + } + map PatternMapOverride { + @pattern("^[g-m]+${'$'}") + key: PatternString, + @pattern("^[g-m]+${'$'}") + value: PatternString + } + union PatternUnion { + first: PatternString, + second: PatternString + } + union PatternUnionOverride { + @pattern("^[g-m]+${'$'}") + first: PatternString, + @pattern("^[g-m]+${'$'}") + second: PatternString + } + @pattern("^[a-m]+${'$'}") + string PatternString + @range(min: 0, max:1000) + integer RangedInteger + """.asSmithyModel() + + private fun loadModel(model: Model): Model = + ConstrainedMemberTransform.transform(OperationNormalizer.transform(model)) + + @Test + fun `non constrained fields should not be changed`() { + val transformedModel = loadModel(outputModelOnly) + + fun checkFieldTargetRemainsSame(fieldName: String) { + checkMemberShapeIsSame( + transformedModel, + outputModelOnly, + "constrainedMemberShape.synthetic#OperationUsingGetOutput\$$fieldName", + "constrainedMemberShape#OperationUsingGetOutput\$$fieldName", + ) { + "OperationUsingGetOutput$fieldName has changed whereas it is not constrained and should have remained same" + } + } + + setOf( + "plainInteger", + "plainLong", + "plainByte", + "plainShort", + "plainFloat", + "patternString", + "plainStringList", + "patternStringList", + "patternStringListOverride", + "plainStructField", + "structWithConstrainedMember", + "structWithConstrainedMemberOverride", + "patternUnion", + "patternUnionOverride", + "patternMap", + "patternMapOverride", + ).forEach(::checkFieldTargetRemainsSame) + + checkMemberShapeIsSame( + transformedModel, + outputModelOnly, + "constrainedMemberShape#StructWithConstrainedMember\$long", + "constrainedMemberShape#StructWithConstrainedMember\$long", + ) + } + + @Test + fun `constrained members should have a different target now`() { + val transformedModel = loadModel(outputModelOnly) + checkMemberShapeChanged( + transformedModel, + outputModelOnly, + "constrainedMemberShape#PatternStringListOverride\$member", + "constrainedMemberShape#PatternStringListOverride\$member", + ) + + fun checkSyntheticFieldTargetChanged(fieldName: String) { + checkMemberShapeChanged( + transformedModel, + outputModelOnly, + "constrainedMemberShape.synthetic#OperationUsingGetOutput\$$fieldName", + "constrainedMemberShape#OperationUsingGetOutput\$$fieldName", + ) { + "constrained member $fieldName should have been changed into a new type." + } + } + + fun checkFieldTargetChanged(memberNameWithContainer: String) { + checkMemberShapeChanged( + transformedModel, + outputModelOnly, + "constrainedMemberShape#$memberNameWithContainer", + "constrainedMemberShape#$memberNameWithContainer", + ) { + "constrained member $memberNameWithContainer should have been changed into a new type." + } + } + + setOf( + "constrainedLong", + "constrainedByte", + "constrainedShort", + "constrainedInteger", + "constrainedString", + "requiredConstrainedString", + "requiredConstrainedLong", + "requiredConstrainedByte", + "requiredConstrainedInteger", + "requiredConstrainedShort", + "constrainedPatternString", + ).forEach(::checkSyntheticFieldTargetChanged) + + setOf( + "StructWithConstrainedMember\$lat", + "PatternMapOverride\$key", + "PatternMapOverride\$value", + "PatternStringListOverride\$member", + ).forEach(::checkFieldTargetChanged) + } + + @Test + fun `extra trait on a constrained member should remain on it`() { + val transformedModel = loadModel(outputModelOnly) + checkShapeHasTrait( + transformedModel, + outputModelOnly, + "constrainedMemberShape.synthetic#OperationUsingGetOutput\$constrainedPatternString", + "constrainedMemberShape#OperationUsingGetOutput\$constrainedPatternString", + "aws.api#data", + ) + } + + private fun runServerCodeGen(model: Model, dirToUse: File? = null, writable: Writable): Path { + val runtimeConfig = + RuntimeConfig(runtimeCrateLocation = RuntimeCrateLocation.Path(File("../rust-runtime").absolutePath)) + + val (context, dir) = generatePluginContext( + model, + runtimeConfig = runtimeConfig, + overrideTestDir = dirToUse, + ) + val codegenDecorator: CombinedServerCodegenDecorator = + CombinedServerCodegenDecorator.fromClasspath(context) + + ServerCodegenVisitor(context, codegenDecorator) + .execute() + + val codegenContext = serverTestCodegenContext(model) + val settings = ServerRustSettings.from(context.model, context.settings) + val rustCrate = RustCrate( + context.fileManifest, + codegenContext.symbolProvider, + settings.codegenConfig, + ) + + // We cannot write to the lib anymore as the RustWriter overwrites it, so writing code directly to check.rs + // and then adding a `mod check;` to the lib.rs + rustCrate.withModule(RustModule.public("check")) { + writable(this) + File("$dir/src/check.rs").writeText(toString()) + } + + val lib = File("$dir/src/lib.rs") + val libContents = lib.readText() + "\nmod check;" + lib.writeText(libContents) + + return dir + } + + @Test + fun `generate code and check member constrained shapes are in the right modules`() { + val dir = runServerCodeGen(outputModelOnly) { + fun RustWriter.testTypeExistsInBuilderModule(typeName: String) { + unitTest( + "builder_module_has_${typeName.toSnakeCase()}", + """ + #[allow(unused_imports)] use crate::output::operation_using_get_output::$typeName; + """, + ) + } + + // All directly constrained members of the output structure should be in the builder module + setOf( + "ConstrainedLong", + "ConstrainedByte", + "ConstrainedShort", + "ConstrainedInteger", + "ConstrainedString", + "RequiredConstrainedString", + "RequiredConstrainedLong", + "RequiredConstrainedByte", + "RequiredConstrainedInteger", + "RequiredConstrainedShort", + "ConstrainedPatternString", + ).forEach(::testTypeExistsInBuilderModule) + + fun Set.generateUseStatements(prefix: String) = + this.joinToString(separator = "\n") { + "#[allow(unused_imports)] use $prefix::$it;" + } + + unitTest( + "map_overridden_enum", + setOf( + "Value", + "value::ConstraintViolation as ValueCV", + "Key", + "key::ConstraintViolation as KeyCV", + ).generateUseStatements("crate::model::pattern_map_override"), + ) + + unitTest( + "union_overridden_enum", + setOf( + "First", + "first::ConstraintViolation as FirstCV", + "Second", + "second::ConstraintViolation as SecondCV", + ).generateUseStatements("crate::model::pattern_union_override"), + ) + + unitTest( + "list_overridden_enum", + setOf( + "Member", + "member::ConstraintViolation as MemberCV", + ).generateUseStatements("crate::model::pattern_string_list_override"), + ) + } + + val env = mapOf("RUSTFLAGS" to "-A dead_code") + "cargo test".runCommand(dir, env) + } + + /** + * Checks that the given member shape: + * 1. Has been changed to a new shape + * 2. New shape has the same type as the original shape's target e.g. float Centigrade, + * float newType + */ + private fun checkMemberShapeChanged( + model: Model, + baseModel: Model, + member: String, + orgModelMember: String, + lazyMessage: () -> Any = ::defaultError, + ) { + val memberId = ShapeId.from(member) + check(model.getShape(memberId).isPresent, lazyMessage) + val memberShape = model.expectShape(memberId).asMemberShape().get() + val memberTargetShape = model.expectShape(memberShape.target) + val orgMemberId = ShapeId.from(orgModelMember) + check(baseModel.getShape(orgMemberId).isPresent, lazyMessage) + val originalShape = baseModel.expectShape(orgMemberId).asMemberShape().get() + val originalTargetShape = model.expectShape(originalShape.target) + + val extractableConstraintTraits = allConstraintTraits - RequiredTrait::class.java + + // New member shape should not have the overridden constraints on it + check(!extractableConstraintTraits.any(memberShape::hasTrait), lazyMessage) + + // Target shape has to be changed to a new shape + check(memberTargetShape.id.name != originalShape.target.name, lazyMessage) + // Target shape's name should match the expected name + val expectedName = memberShape.container.name.substringAfter('#') + + memberShape.memberName.substringBefore('#').toPascalCase() + check(memberTargetShape.id.name == expectedName, lazyMessage) + // New shape should have all of the constraint traits that were on the member shape, + // and it should also have the traits that the target type contains. + val originalConstrainedTraits = + originalShape.allTraits.values.filter { allConstraintTraits.contains(it.javaClass) }.toSet() + val newShapeConstrainedTraits = + memberTargetShape.allTraits.values.filter { allConstraintTraits.contains(it.javaClass) }.toSet() + + val leftOutConstraintTrait = originalConstrainedTraits - newShapeConstrainedTraits + check( + leftOutConstraintTrait.isEmpty() || leftOutConstraintTrait.all { + it.toShapeId() == RequiredTrait.ID + }, + lazyMessage, + ) + + // In case the target shape has some more constraints, which the member shape did not override, + // then those still need to apply on the new standalone shape that has been defined. + val leftOverTraits = originalTargetShape.allTraits.values + .filter { beforeOverridingTrait -> originalConstrainedTraits.none { beforeOverridingTrait.toShapeId() == it.toShapeId() } } + val allNewShapeTraits = memberTargetShape.allTraits.values.toList() + check((leftOverTraits + newShapeConstrainedTraits).all { it in allNewShapeTraits }, lazyMessage) + } + + private fun defaultError() = "test failed" + + /** + * Checks that the given shape has not changed in the transformed model and is exactly + * the same as the original model + */ + private fun checkMemberShapeIsSame( + model: Model, + baseModel: Model, + member: String, + orgModelMember: String, + lazyMessage: () -> Any = ::defaultError, + ) { + val memberId = ShapeId.from(member) + check(model.getShape(memberId).isPresent, lazyMessage) + + val memberShape = model.expectShape(memberId).asMemberShape().get() + val memberTargetShape = model.expectShape(memberShape.target) + val originalShape = baseModel.expectShape(ShapeId.from(orgModelMember)).asMemberShape().get() + + // Member shape should not have any constraints on it + check(!memberShape.hasConstraintTrait(), lazyMessage) + // Target shape has to be same as the original shape + check(memberTargetShape.id == originalShape.target, lazyMessage) + } + + private fun checkShapeHasTrait( + model: Model, + orgModel: Model, + member: String, + orgModelMember: String, + traitName: String, + ) { + val memberId = ShapeId.from(member) + val memberShape = model.expectShape(memberId).asMemberShape().get() + val orgMemberShape = orgModel.expectShape(ShapeId.from(orgModelMember)).asMemberShape().get() + + check(memberShape.allTraits.keys.contains(ShapeId.from(traitName))) + { "given $member does not have the $traitName applied to it" } + check(orgMemberShape.allTraits.keys.contains(ShapeId.from(traitName))) + { "given $member does not have the $traitName applied to it in the original model" } + + val newMemberTrait = memberShape.allTraits[ShapeId.from(traitName)] + val oldMemberTrait = orgMemberShape.allTraits[ShapeId.from(traitName)] + check(newMemberTrait == oldMemberTrait) { "contents of the two traits do not match in the transformed model" } + } +} diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt new file mode 100644 index 0000000000..00480acee8 --- /dev/null +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt @@ -0,0 +1,259 @@ +package software.amazon.smithy.rust.codegen.server.smithy + +import org.junit.jupiter.api.Test +import software.amazon.smithy.model.Model +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.Visibility +import software.amazon.smithy.rust.codegen.core.rustlang.comment +import software.amazon.smithy.rust.codegen.core.rustlang.rust +import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock +import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate +import software.amazon.smithy.rust.codegen.core.smithy.InputsModule +import software.amazon.smithy.rust.codegen.core.smithy.ModelsModule +import software.amazon.smithy.rust.codegen.core.smithy.OutputsModule +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeCrateLocation +import software.amazon.smithy.rust.codegen.core.smithy.RustCrate +import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace +import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel +import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest +import software.amazon.smithy.rust.codegen.core.testutil.generatePluginContext +import software.amazon.smithy.rust.codegen.core.testutil.unitTest +import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext +import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestSymbolProvider +import java.io.File +import kotlin.collections.Map.Entry + +class RustCrateInlineModuleComposingWriterTest { + private val rustCrate: RustCrate + private val codegenContext: ServerCodegenContext + private val model: Model = """ + ${'$'}version: "2.0" + namespace test + + use aws.api#data + use aws.protocols#restJson1 + + @title("Weather Service") + @restJson1 + service WeatherService { + operations: [MalformedPatternOverride] + } + + @suppress(["UnstableTrait"]) + @http(uri: "/MalformedPatternOverride", method: "GET") + operation MalformedPatternOverride { + output: MalformedPatternOverrideInput, + errors: [] + } + + structure MalformedPatternOverrideInput { + @pattern("^[g-m]+${'$'}") + string: PatternString, + } + + @pattern("^[a-m]+${'$'}") + string PatternString + """.trimIndent().asSmithyModel() + + init { + codegenContext = serverTestCodegenContext(model) + val runtimeConfig = + RuntimeConfig(runtimeCrateLocation = RuntimeCrateLocation.Path(File("../rust-runtime").absolutePath)) + + val (context, _) = generatePluginContext( + model, + runtimeConfig = runtimeConfig, + ) + val settings = ServerRustSettings.from(context.model, context.settings) + rustCrate = RustCrate(context.fileManifest, codegenContext.symbolProvider, settings.codegenConfig) + } + + private fun createTestInlineModule(parentModule: RustModule, moduleName : String) : RustModule.LeafModule = + RustModule.new( + moduleName, + visibility = Visibility.PUBLIC, + documentation = moduleName, + parent = parentModule, + inline = true, + ) + + private fun createTestOrphanInlineModule(moduleName : String) : RustModule.LeafModule = + RustModule.new( + moduleName, + visibility = Visibility.PUBLIC, + documentation = moduleName, + parent = RustModule.LibRs, + inline = true, + ) + + private fun helloWorld(writer: RustWriter, moduleName: String) { + writer.rustBlock("pub fn hello_world()") { + writer.comment("Module $moduleName") + writer.rust("""println!("from inside $moduleName");""") + } + } + + private fun byeWorld(writer: RustWriter, moduleName: String) { + writer.rustBlock("pub fn bye_world()") { + writer.comment("Module $moduleName") + writer.rust("""println!("from inside $moduleName");""") + } + } + + @Test + fun `simple inline module works`() { + val testProject = TestWorkspace.testProject(serverTestSymbolProvider(model)) + val moduleA = createTestInlineModule(ModelsModule, "a") + testProject.withModule(ModelsModule) { + testProject.getInlineModuleWriter().withInlineModule(this, moduleA) { + helloWorld(this, "a") + } + } + + testProject.getInlineModuleWriter().render() + testProject.withModule(ModelsModule) { + this.unitTest("test_a") { + rust("crate::model::a::hello_world();") + } + } + testProject.compileAndTest() + } + + @Test + fun `creating nested modules works from different rustWriters`() { + // Define the following functions in different inline modules. + // crate::model::a::hello_world(); + // crate::model::a::bye_world(); + // crate::model::b::hello_world(); + // crate::model::b::bye_world(); + // crate::model::b::c::hello_world(); + // crate::model::b::c::bye_world(); + // crate::input::e::hello_world(); + // crate::output::f::hello_world(); + // crate::output::f::g::hello_world(); + // crate::output::h::hello_world(); + // crate::output::h::i::hello_world(); + + val testProject = TestWorkspace.testProject(serverTestSymbolProvider(model)) + val modules = hashMapOf( + "a" to createTestOrphanInlineModule("a"), + "d" to createTestOrphanInlineModule("d"), + "e" to createTestOrphanInlineModule("e"), + "i" to createTestOrphanInlineModule("i"), + ) + + modules["b"] = createTestInlineModule(ModelsModule, "b") + modules["c"] = createTestInlineModule(modules["b"]!!, "c") + modules["f"] = createTestInlineModule(OutputsModule, "f") + modules["g"] = createTestInlineModule(modules["f"]!!, "g") + modules["h"] = createTestInlineModule(OutputsModule, "h") + + testProject.withModule(ModelsModule) { + testProject.getInlineModuleWriter().withInlineModule(this, modules["a"]!!) { + helloWorld(this, "a") + } + testProject.getInlineModuleWriter().withInlineModule(this, modules["b"]!!) { + helloWorld(this, "b") + testProject.getInlineModuleWriter().withInlineModule(this, modules["c"]!!) { + byeWorld(this, "b::c") + } + } + // Writing to the same module crate::model::a second time should work. + testProject.getInlineModuleWriter().withInlineModule(this, modules["a"]!!) { + byeWorld(this, "a") + } + // Writing to model::b, when model::b and model::b::c have already been written to + // should work. + testProject.getInlineModuleWriter().withInlineModule(this, modules["b"]!!) { + byeWorld(this, "b") + } + } + + // Write directly to an inline module without specifying the immediate parent. crate::model::b::c + // should have a `hello_world` fn in it now. + testProject.withModule(ModelsModule) { + testProject.getInlineModuleWriter().withInlineModuleHierarchy(this, modules["c"]!!) { + helloWorld(this, "c") + } + } + // Write to a different top level module to confirm that works. + testProject.withModule(InputsModule) { + testProject.getInlineModuleWriter().withInlineModuleHierarchy(this, modules["e"]!!) { + helloWorld(this, "e") + } + } + + // Create a descendent inner module crate::output::f::g and then try writing to the intermediate inner module + // that did not exist before the descendent was dded. + testProject.getInlineModuleWriter().withInlineModuleHierarchyUsingCrate(testProject, modules["f"]!!) { + testProject.getInlineModuleWriter().withInlineModuleHierarchyUsingCrate(testProject, modules["g"]!!) { + helloWorld(this, "g") + } + } + + testProject.getInlineModuleWriter().withInlineModuleHierarchyUsingCrate(testProject, modules["f"]!!) { + helloWorld(this, "f") + } + + + // It should work even if the inner descendent module was added using `withInlineModuleHierarchy` and then + // code is added to the intermediate module using `withInlineModuleHierarchyUsingCrate` + testProject.withModule(OutputsModule) { + testProject.getInlineModuleWriter().withInlineModuleHierarchy(this, modules["h"]!!) { + testProject.getInlineModuleWriter().withInlineModuleHierarchy(this, modules["i"]!!) { + helloWorld(this, "i") + } + testProject.withModule(ModelsModule) { + // While writing to output::h::i, it should be able to a completely different module + testProject.getInlineModuleWriter().withInlineModuleHierarchy(this, modules["b"]!!) { + rustBlock("pub fn some_other_writer_wrote_this()") { + rust("""println!("from inside crate::model::b::some_other_writer_wrote_this");""") + } + } + } + } + } + testProject.getInlineModuleWriter().withInlineModuleHierarchyUsingCrate(testProject, modules["h"]!!) { + helloWorld(this, "h") + } + + // Render all of the code. + testProject.getInlineModuleWriter().render() + + testProject.withModule(ModelsModule) { + this.unitTest("test_a") { + rust("crate::model::a::hello_world();") + rust("crate::model::a::bye_world();") + } + this.unitTest("test_b") { + rust("crate::model::b::hello_world();") + rust("crate::model::b::bye_world();") + } + this.unitTest("test_someother_writer_wrote") { + rust("crate::model::b::some_other_writer_wrote_this();") + } + this.unitTest("test_b_c") { + rust("crate::model::b::c::hello_world();") + rust("crate::model::b::c::bye_world();") + } + this.unitTest("test_e") { + rust("crate::input::e::hello_world();") + } + this.unitTest("test_f") { + rust("crate::output::f::hello_world();") + } + this.unitTest("test_g") { + rust("crate::output::f::g::hello_world();") + } + this.unitTest("test_h") { + rust("crate::output::h::hello_world();") + } + this.unitTest("test_h_i") { + rust("crate::output::h::i::hello_world();") + } + } + testProject.compileAndTest() + } +} diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraintsAreNotUsedTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraintsAreNotUsedTest.kt index 7e111f758c..36ea61449b 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraintsAreNotUsedTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraintsAreNotUsedTest.kt @@ -76,39 +76,6 @@ internal class ValidateUnsupportedConstraintsAreNotUsedTest { """.trimIndent() } - @Test - fun `it should detect when unsupported constraint traits on member shapes are used`() { - val model = - """ - $baseModel - - structure TestInputOutput { - @length(min: 1, max: 69) - lengthString: String - } - """.asSmithyModel() - val validationResult = validateModel(model) - - validationResult.messages shouldHaveSize 1 - validationResult.messages[0].message shouldContain "The member shape `test#TestInputOutput\$lengthString` has the constraint trait `smithy.api#length` attached" - } - - @Test - fun `it should not detect when the required trait on a member shape is used`() { - val model = - """ - $baseModel - - structure TestInputOutput { - @required - string: String - } - """.asSmithyModel() - val validationResult = validateModel(model) - - validationResult.messages shouldHaveSize 0 - } - private val constraintTraitOnStreamingBlobShapeModel = """ $baseModel diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt index 0cabbac74d..98e6dbf7d4 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt @@ -24,6 +24,7 @@ import software.amazon.smithy.rust.codegen.core.util.dq import software.amazon.smithy.rust.codegen.core.util.lookup import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator +import software.amazon.smithy.rust.codegen.server.smithy.createTestInlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext import java.util.stream.Stream @@ -69,9 +70,10 @@ class ConstrainedBlobGeneratorTest { project.withModule(ServerRustModule.Model) { addDependency(RuntimeType.blob(codegenContext.runtimeConfig).toSymbol()) + // FZ Rebase ConstrainedBlobGenerator( codegenContext, - this, + this.createTestInlineModuleCreator(), constrainedBlobShape, SmithyValidationExceptionConversionGenerator(codegenContext), ).render() @@ -127,13 +129,20 @@ class ConstrainedBlobGeneratorTest { val writer = RustWriter.forModule(ServerRustModule.Model.name) + // FZ rebase ConstrainedBlobGenerator( codegenContext, - writer, + writer.createTestInlineModuleCreator(), constrainedBlobShape, SmithyValidationExceptionConversionGenerator(codegenContext), ).render() + // FZ rebase main + // ConstrainedBlobGenerator(codegenContext, + // writer.createTestInlineModuleCreator(), + // writer, + // constrainedBlobShape).render() + // Check that the wrapped type is `pub(crate)`. writer.toString() shouldContain "pub struct ConstrainedBlob(pub(crate) aws_smithy_types::Blob);" } diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt index 5d0e19cbc0..5c542faa74 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt @@ -34,6 +34,7 @@ import software.amazon.smithy.rust.codegen.core.util.lookup import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator +import software.amazon.smithy.rust.codegen.server.smithy.createTestInlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.transformers.ShapesReachableFromOperationInputTagger import java.util.stream.Stream @@ -285,9 +286,10 @@ class ConstrainedCollectionGeneratorTest { ) { val constraintsInfo = CollectionTraitInfo.fromShape(constrainedCollectionShape, codegenContext.symbolProvider) ConstrainedCollectionGenerator(codegenContext, writer, constrainedCollectionShape, constraintsInfo).render() + // FZ rebase CollectionConstraintViolationGenerator( codegenContext, - writer, + writer.createTestInlineModuleCreator(), constrainedCollectionShape, constraintsInfo, SmithyValidationExceptionConversionGenerator(codegenContext), diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt index f9c84b7db8..c54523fe9f 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt @@ -25,6 +25,7 @@ import software.amazon.smithy.rust.codegen.core.util.lookup import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator +import software.amazon.smithy.rust.codegen.server.smithy.createTestInlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.transformers.ShapesReachableFromOperationInputTagger import java.util.stream.Stream @@ -154,9 +155,10 @@ class ConstrainedMapGeneratorTest { constrainedMapShape: MapShape, ) { ConstrainedMapGenerator(codegenContext, writer, constrainedMapShape).render() + // FZ rebase MapConstraintViolationGenerator( codegenContext, - writer, + writer.createTestInlineModuleCreator(), constrainedMapShape, SmithyValidationExceptionConversionGenerator(codegenContext), ).render() diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt index 0f26bdaaee..a253296b96 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt @@ -21,6 +21,7 @@ import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.lookup import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator +import software.amazon.smithy.rust.codegen.server.smithy.createTestInlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext import java.util.stream.Stream @@ -71,10 +72,11 @@ class ConstrainedNumberGeneratorTest { val project = TestWorkspace.testProject(symbolProvider) + // FZ rebase project.withModule(ServerRustModule.Model) { ConstrainedNumberGenerator( codegenContext, - this, + this.createTestInlineModuleCreator(), shape, SmithyValidationExceptionConversionGenerator(codegenContext), ).render() @@ -138,9 +140,10 @@ class ConstrainedNumberGeneratorTest { val codegenContext = serverTestCodegenContext(model) val writer = RustWriter.forModule(ServerRustModule.Model.name) + // FZ rebase ConstrainedNumberGenerator( codegenContext, - writer, + writer.createTestInlineModuleCreator(), constrainedShape, SmithyValidationExceptionConversionGenerator(codegenContext), ).render() diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt index 6c8ddd8d67..a736cfe69b 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt @@ -24,6 +24,7 @@ import software.amazon.smithy.rust.codegen.core.util.CommandFailed import software.amazon.smithy.rust.codegen.core.util.lookup import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator +import software.amazon.smithy.rust.codegen.server.smithy.createTestInlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext import java.util.stream.Stream @@ -82,9 +83,11 @@ class ConstrainedStringGeneratorTest { val project = TestWorkspace.testProject(symbolProvider) + // FZ rebase project.withModule(ServerRustModule.Model) { ConstrainedStringGenerator( codegenContext, + this.createTestInlineModuleCreator(), this, constrainedStringShape, SmithyValidationExceptionConversionGenerator(codegenContext), @@ -142,8 +145,10 @@ class ConstrainedStringGeneratorTest { val writer = RustWriter.forModule(ServerRustModule.Model.name) + // FZ rebase ConstrainedStringGenerator( codegenContext, + writer.createTestInlineModuleCreator(), writer, constrainedStringShape, SmithyValidationExceptionConversionGenerator(codegenContext), @@ -172,16 +177,19 @@ class ConstrainedStringGeneratorTest { val project = TestWorkspace.testProject(codegenContext.symbolProvider) + // FZ rebase project.withModule(ServerRustModule.Model) { val validationExceptionConversionGenerator = SmithyValidationExceptionConversionGenerator(codegenContext) ConstrainedStringGenerator( codegenContext, + this.createTestInlineModuleCreator(), this, constrainedStringShape, validationExceptionConversionGenerator, ).render() ConstrainedStringGenerator( codegenContext, + this.createTestInlineModuleCreator(), this, sensitiveConstrainedStringShape, validationExceptionConversionGenerator, @@ -222,9 +230,11 @@ class ConstrainedStringGeneratorTest { val codegenContext = serverTestCodegenContext(model) val project = TestWorkspace.testProject(codegenContext.symbolProvider) + // FZ rebase project.withModule(ServerRustModule.Model) { ConstrainedStringGenerator( codegenContext, + this.createTestInlineModuleCreator(), this, constrainedStringShape, SmithyValidationExceptionConversionGenerator(codegenContext), diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderDefaultValuesTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderDefaultValuesTest.kt index 751d62bc8e..e64d0c930c 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderDefaultValuesTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderDefaultValuesTest.kt @@ -20,6 +20,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.withBlock import software.amazon.smithy.rust.codegen.core.rustlang.writable +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.StructureGenerator import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace @@ -105,10 +106,10 @@ class ServerBuilderDefaultValuesTest { project.withModule(RustModule.public("model")) { when (builderGeneratorKind) { BuilderGeneratorKind.SERVER_BUILDER_GENERATOR -> { - writeServerBuilderGenerator(this, model, symbolProvider) + writeServerBuilderGenerator(project, this, model, symbolProvider) } BuilderGeneratorKind.SERVER_BUILDER_GENERATOR_WITHOUT_PUBLIC_CONSTRAINED_TYPES -> { - writeServerBuilderGeneratorWithoutPublicConstrainedTypes(this, model, symbolProvider) + writeServerBuilderGeneratorWithoutPublicConstrainedTypes(project, this, model, symbolProvider) } } @@ -168,7 +169,7 @@ class ServerBuilderDefaultValuesTest { .map { it.key to "${it.value}.into()" } } - private fun writeServerBuilderGeneratorWithoutPublicConstrainedTypes(writer: RustWriter, model: Model, symbolProvider: RustSymbolProvider) { + private fun writeServerBuilderGeneratorWithoutPublicConstrainedTypes(rustCrate: RustCrate, writer: RustWriter, model: Model, symbolProvider: RustSymbolProvider) { val struct = model.lookup("com.test#MyStruct") val codegenContext = serverTestCodegenContext( model, @@ -181,7 +182,7 @@ class ServerBuilderDefaultValuesTest { writer.implBlock(symbolProvider.toSymbol(struct)) { builderGenerator.renderConvenienceMethod(writer) } - builderGenerator.render(writer) + builderGenerator.render(rustCrate, writer) ServerEnumGenerator( codegenContext, @@ -191,7 +192,7 @@ class ServerBuilderDefaultValuesTest { StructureGenerator(model, symbolProvider, writer, struct, emptyList()).render() } - private fun writeServerBuilderGenerator(writer: RustWriter, model: Model, symbolProvider: RustSymbolProvider) { + private fun writeServerBuilderGenerator(rustCrate: RustCrate, writer: RustWriter, model: Model, symbolProvider: RustSymbolProvider) { val struct = model.lookup("com.test#MyStruct") val codegenContext = serverTestCodegenContext(model) val builderGenerator = ServerBuilderGenerator(codegenContext, struct, SmithyValidationExceptionConversionGenerator(codegenContext)) @@ -199,7 +200,7 @@ class ServerBuilderDefaultValuesTest { writer.implBlock(symbolProvider.toSymbol(struct)) { builderGenerator.renderConvenienceMethod(writer) } - builderGenerator.render(writer) + builderGenerator.render(rustCrate, writer) ServerEnumGenerator( codegenContext, diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorTest.kt index 2748c6721e..8fef67bbfc 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorTest.kt @@ -10,6 +10,11 @@ import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.implBlock import software.amazon.smithy.rust.codegen.core.smithy.generators.StructureGenerator +import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget +import software.amazon.smithy.rust.codegen.core.smithy.RustCrate +import software.amazon.smithy.rust.codegen.core.smithy.generators.StructureGenerator +import software.amazon.smithy.rust.codegen.core.smithy.generators.implBlock +import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest import software.amazon.smithy.rust.codegen.core.util.lookup @@ -37,9 +42,12 @@ class ServerBuilderGeneratorTest { val codegenContext = serverTestCodegenContext(model) val writer = RustWriter.forModule("model") val shape = model.lookup("test#Credentials") + + // FZ rebase StructureGenerator(model, codegenContext.symbolProvider, writer, shape, emptyList()).render() val builderGenerator = ServerBuilderGenerator(codegenContext, shape, SmithyValidationExceptionConversionGenerator(codegenContext)) - builderGenerator.render(writer) + val project = TestWorkspace.testProject() + builderGenerator.render(project, writer) writer.implBlock(codegenContext.symbolProvider.toSymbol(shape)) { builderGenerator.renderConvenienceMethod(this) } diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiatorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiatorTest.kt index c7f2b2e5ff..a279966a51 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiatorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiatorTest.kt @@ -138,10 +138,11 @@ class ServerInstantiatorTest { val data = Node.parse("{}") val project = TestWorkspace.testProject() + // FZ rebase project.withModule(ServerRustModule.Model) { - structure.serverRenderWithModelBuilder(model, symbolProvider, this) - inner.serverRenderWithModelBuilder(model, symbolProvider, this) - nestedStruct.serverRenderWithModelBuilder(model, symbolProvider, this) + structure.serverRenderWithModelBuilder(project, model, symbolProvider, this) + inner.serverRenderWithModelBuilder(project, model, symbolProvider, this) + nestedStruct.serverRenderWithModelBuilder(project, model, symbolProvider, this) UnionGenerator(model, symbolProvider, this, union).render() withInlineModule(RustModule.inlineTests()) { diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationErrorGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationErrorGeneratorTest.kt index 31acf95b47..90b49daa5a 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationErrorGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationErrorGeneratorTest.kt @@ -53,7 +53,7 @@ class ServerOperationErrorGeneratorTest { val project = TestWorkspace.testProject(symbolProvider) project.withModule(ServerRustModule.Error) { listOf("FooException", "ComplexError", "InvalidGreeting", "Deprecated").forEach { - model.lookup("error#$it").serverRenderWithModelBuilder(model, symbolProvider, this) + model.lookup("error#$it").serverRenderWithModelBuilder(project, model, symbolProvider, this) } ServerOperationErrorGenerator( model, diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt index 64117fd0b7..0800f49942 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt @@ -15,6 +15,7 @@ import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.lookup import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator +import software.amazon.smithy.rust.codegen.server.smithy.createTestInlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverRenderWithModelBuilder import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext @@ -49,13 +50,17 @@ class UnconstrainedCollectionGeneratorTest { val project = TestWorkspace.testProject(symbolProvider) + // FZ rebase project.withModule(ServerRustModule.Model) { - model.lookup("test#StructureC").serverRenderWithModelBuilder(model, symbolProvider, this) + model.lookup("test#StructureC").serverRenderWithModelBuilder(project, model, symbolProvider, this) } project.withModule(ServerRustModule.ConstrainedModule) { listOf(listA, listB).forEach { - PubCrateConstrainedCollectionGenerator(codegenContext, this, it).render() + PubCrateConstrainedCollectionGenerator(codegenContext, + //this, + this.createTestInlineModuleCreator(), + it).render() } } project.withModule(ServerRustModule.UnconstrainedModule) unconstrainedModuleWriter@{ @@ -63,13 +68,15 @@ class UnconstrainedCollectionGeneratorTest { listOf(listA, listB).forEach { UnconstrainedCollectionGenerator( codegenContext, - this@unconstrainedModuleWriter, + //this@unconstrainedModuleWriter, + this@unconstrainedModuleWriter.createTestInlineModuleCreator(), it, ).render() + // FZ rebase CollectionConstraintViolationGenerator( codegenContext, - this@modelsModuleWriter, + this@modelsModuleWriter.createTestInlineModuleCreator(), it, CollectionTraitInfo.fromShape(it, codegenContext.constrainedShapeSymbolProvider), SmithyValidationExceptionConversionGenerator(codegenContext), diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt index b091d7a38d..0478c341da 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt @@ -16,6 +16,7 @@ import software.amazon.smithy.rust.codegen.core.util.lookup import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule.Model import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator +import software.amazon.smithy.rust.codegen.server.smithy.createTestInlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverRenderWithModelBuilder import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext @@ -52,23 +53,29 @@ class UnconstrainedMapGeneratorTest { val project = TestWorkspace.testProject(symbolProvider, debugMode = true) + // FZ rebase project.withModule(Model) { - model.lookup("test#StructureC").serverRenderWithModelBuilder(model, symbolProvider, this) + model.lookup("test#StructureC").serverRenderWithModelBuilder(project, model, symbolProvider, this) } project.withModule(ServerRustModule.ConstrainedModule) { listOf(mapA, mapB).forEach { - PubCrateConstrainedMapGenerator(codegenContext, this, it).render() + PubCrateConstrainedMapGenerator(codegenContext, + //this, + this.createTestInlineModuleCreator(), + it).render() } } project.withModule(ServerRustModule.UnconstrainedModule) unconstrainedModuleWriter@{ project.withModule(Model) modelsModuleWriter@{ listOf(mapA, mapB).forEach { - UnconstrainedMapGenerator(codegenContext, this@unconstrainedModuleWriter, it).render() + UnconstrainedMapGenerator(codegenContext, + this@unconstrainedModuleWriter.createTestInlineModuleCreator(), it).render() + // FZ rebase MapConstraintViolationGenerator( codegenContext, - this@modelsModuleWriter, + this@modelsModuleWriter.createTestInlineModuleCreator(), it, SmithyValidationExceptionConversionGenerator(codegenContext), ).render() diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt index 2b745e270b..61b96a6d66 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt @@ -6,9 +6,11 @@ package software.amazon.smithy.rust.codegen.server.smithy.generators import org.junit.jupiter.api.Test +import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.model.shapes.UnionShape 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.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest @@ -42,15 +44,17 @@ class UnconstrainedUnionGeneratorTest { val project = TestWorkspace.testProject(symbolProvider) project.withModule(ServerRustModule.Model) { - model.lookup("test#Structure").serverRenderWithModelBuilder(model, symbolProvider, this) + model.lookup("test#Structure").serverRenderWithModelBuilder(project, model, symbolProvider, this) } project.withModule(ServerRustModule.Model) { UnionGenerator(model, symbolProvider, this, unionShape, renderUnknownVariant = false).render() } + + // FZ rebase project.withModule(ServerRustModule.UnconstrainedModule) unconstrainedModuleWriter@{ project.withModule(ServerRustModule.Model) modelsModuleWriter@{ - UnconstrainedUnionGenerator(codegenContext, this@unconstrainedModuleWriter, this@modelsModuleWriter, unionShape).render() + UnconstrainedUnionGenerator(codegenContext, this@unconstrainedModuleWriter.createInlineModuleCreator(), this@modelsModuleWriter, unionShape).render() this@unconstrainedModuleWriter.unitTest( name = "unconstrained_union_fail_to_constrain", diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamBaseRequirements.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamBaseRequirements.kt index d59eed6acd..46adcc3d7b 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamBaseRequirements.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamBaseRequirements.kt @@ -16,6 +16,7 @@ import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.implBlock import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget +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.StructureGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.error.ErrorImplGenerator @@ -68,21 +69,23 @@ abstract class ServerEventStreamBaseRequirements : EventStreamTestRequirements Date: Wed, 15 Feb 2023 21:34:26 +0000 Subject: [PATCH 02/18] ModelModule to ServerRustModule.model --- .../smithy/PythonServerCodegenVisitor.kt | 1 + .../smithy/ConstrainedShapeSymbolProvider.kt | 1 + .../ConstraintViolationSymbolProvider.kt | 2 +- .../rust/codegen/server/smithy/Constraints.kt | 6 ++-- .../server/smithy/ServerCodegenVisitor.kt | 5 ++-- .../UnconstrainedShapeSymbolProvider.kt | 1 - .../smithy/testutil/ServerTestHelpers.kt | 2 +- .../smithy/ConstraintsMemberShapeTest.kt | 6 ++++ ...ustCrateInlineModuleComposingWriterTest.kt | 28 ++++++++----------- .../ConstrainedBlobGeneratorTest.kt | 2 ++ .../ConstrainedNumberGeneratorTest.kt | 2 ++ .../generators/ServerBuilderGeneratorTest.kt | 4 --- .../UnconstrainedUnionGeneratorTest.kt | 3 +- .../ServerEventStreamBaseRequirements.kt | 4 ++- 14 files changed, 36 insertions(+), 31 deletions(-) diff --git a/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/PythonServerCodegenVisitor.kt b/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/PythonServerCodegenVisitor.kt index 445ef1ccf2..0b113a9121 100644 --- a/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/PythonServerCodegenVisitor.kt +++ b/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/PythonServerCodegenVisitor.kt @@ -78,6 +78,7 @@ class PythonServerCodegenVisitor( serviceShape: ServiceShape, symbolVisitorConfig: SymbolVisitorConfig, publicConstrainedTypes: Boolean, + includeConstraintShapeProvider: Boolean, ) = RustServerCodegenPythonPlugin.baseSymbolProvider(model, serviceShape, symbolVisitorConfig, publicConstrainedTypes) val serverSymbolProviders = ServerSymbolProviders.from( diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt index 756b659ef9..d75f377d0e 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt @@ -24,6 +24,7 @@ import software.amazon.smithy.model.traits.LengthTrait 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.RustType +import software.amazon.smithy.rust.codegen.core.rustlang.Visibility import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.WrappingSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.contextName diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt index 83fa724605..30775127b5 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt @@ -101,7 +101,7 @@ class ConstraintViolationSymbolProvider( Pair(overriddenMemberModule.second, RustReservedWords.escapeIfNeeded(name).toSnakeCase()) } else { // Need to use the context name so we get the correct name for maps. - Pair(ModelsModule, RustReservedWords.escapeIfNeeded(this.contextName(serviceShape)).toSnakeCase()) + Pair(ServerRustModule.Model, RustReservedWords.escapeIfNeeded(this.contextName(serviceShape)).toSnakeCase()) } return RustModule.new( diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt index 800c171ab8..98ecb95a70 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt @@ -32,8 +32,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.RustReservedWords import software.amazon.smithy.rust.codegen.core.rustlang.Visibility import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext import software.amazon.smithy.rust.codegen.core.smithy.DirectedWalker -import software.amazon.smithy.rust.codegen.core.smithy.ModelsModule -import software.amazon.smithy.rust.codegen.core.smithy.contextName import software.amazon.smithy.rust.codegen.core.smithy.isOptional import software.amazon.smithy.rust.codegen.core.smithy.module import software.amazon.smithy.rust.codegen.core.util.UNREACHABLE @@ -212,11 +210,11 @@ fun Shape.getParentAndInlineModuleForConstrainedMember(symbolProvider: SymbolPro val innerModule = RustModule.new( name = name, visibility = Visibility.PUBCRATE, - parent = ModelsModule, + parent = ServerRustModule.Model, inline = true, ) - Pair(ModelsModule, innerModule) + Pair(ServerRustModule.Model, innerModule) } } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt index f1d1a6bfd6..be1447367e 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt @@ -300,7 +300,7 @@ open class ServerCodegenVisitor( ) { if (codegenContext.settings.codegenConfig.publicConstrainedTypes || shape.isReachableFromOperationInput()) { val serverBuilderGenerator = ServerBuilderGenerator(codegenContext, shape, validationExceptionConversionGenerator) - serverBuilderGenerator.render(writer) + serverBuilderGenerator.render(rustCrate, writer) // FZ Rebase mine // val serverBuilderGenerator = ServerBuilderGenerator(codegenContext, shape) // serverBuilderGenerator.render(rustCrate, writer) @@ -503,7 +503,8 @@ open class ServerCodegenVisitor( rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.Model, shape, codegenContext) { ConstrainedNumberGenerator(codegenContext, rustCrate.createInlineModuleCreator(), - shape, + this, + shape, validationExceptionConversionGenerator, ).render() } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProvider.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProvider.kt index 5c90d13c9a..e892f1dd15 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProvider.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProvider.kt @@ -21,7 +21,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.RustReservedWords import software.amazon.smithy.rust.codegen.core.rustlang.RustType import software.amazon.smithy.rust.codegen.core.rustlang.Visibility import software.amazon.smithy.rust.codegen.core.smithy.Default -import software.amazon.smithy.rust.codegen.core.smithy.ModelsModule import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.WrappingSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.contextName diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt index 6b113ddda4..61f4fc1912 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt @@ -121,7 +121,7 @@ fun serverTestCodegenContext( /** * In tests, we frequently need to generate a struct, a builder, and an impl block to access said builder. */ -fun StructureShape.serverRenderWithModelBuilder(model: Model, symbolProvider: RustSymbolProvider, writer: RustWriter) { +fun StructureShape.serverRenderWithModelBuilder(rustCrate: RustCrate, model: Model, symbolProvider: RustSymbolProvider, writer: RustWriter) { StructureGenerator(model, symbolProvider, writer, this, emptyList()).render() val serverCodegenContext = serverTestCodegenContext(model) // Note that this always uses `ServerBuilderGenerator` and _not_ `ServerBuilderGeneratorWithoutPublicConstrainedTypes`, diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt index d2967ebc00..3ae0383b06 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt @@ -1,6 +1,7 @@ package software.amazon.smithy.rust.codegen.server.smithy import org.junit.jupiter.api.Test +import software.amazon.smithy.codegen.core.ReservedWordSymbolProvider import software.amazon.smithy.model.Model import software.amazon.smithy.model.shapes.ShapeId import software.amazon.smithy.model.traits.RequiredTrait @@ -20,11 +21,16 @@ import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.runCommand import software.amazon.smithy.rust.codegen.core.util.toPascalCase import software.amazon.smithy.rust.codegen.core.util.toSnakeCase +import software.amazon.smithy.rust.codegen.server.smithy.customizations.CustomValidationExceptionWithReasonDecorator +import software.amazon.smithy.rust.codegen.server.smithy.customizations.ServerRequiredCustomizations +import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionDecorator import software.amazon.smithy.rust.codegen.server.smithy.customize.CombinedServerCodegenDecorator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestSymbolProvider import java.io.File import java.nio.file.Path +import java.util.logging.Level +import java.util.logging.Logger class ConstraintsMemberShapeTest { private val outputModelOnly = """ diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt index 00480acee8..b067a5d123 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt @@ -8,10 +8,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.Visibility import software.amazon.smithy.rust.codegen.core.rustlang.comment import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock -import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate -import software.amazon.smithy.rust.codegen.core.smithy.InputsModule -import software.amazon.smithy.rust.codegen.core.smithy.ModelsModule -import software.amazon.smithy.rust.codegen.core.smithy.OutputsModule import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig import software.amazon.smithy.rust.codegen.core.smithy.RuntimeCrateLocation import software.amazon.smithy.rust.codegen.core.smithy.RustCrate @@ -105,15 +101,15 @@ class RustCrateInlineModuleComposingWriterTest { @Test fun `simple inline module works`() { val testProject = TestWorkspace.testProject(serverTestSymbolProvider(model)) - val moduleA = createTestInlineModule(ModelsModule, "a") - testProject.withModule(ModelsModule) { + val moduleA = createTestInlineModule(ServerRustModule.Model, "a") + testProject.withModule(ServerRustModule.Model) { testProject.getInlineModuleWriter().withInlineModule(this, moduleA) { helloWorld(this, "a") } } testProject.getInlineModuleWriter().render() - testProject.withModule(ModelsModule) { + testProject.withModule(ServerRustModule.Model) { this.unitTest("test_a") { rust("crate::model::a::hello_world();") } @@ -144,13 +140,13 @@ class RustCrateInlineModuleComposingWriterTest { "i" to createTestOrphanInlineModule("i"), ) - modules["b"] = createTestInlineModule(ModelsModule, "b") + modules["b"] = createTestInlineModule(ServerRustModule.Model, "b") modules["c"] = createTestInlineModule(modules["b"]!!, "c") - modules["f"] = createTestInlineModule(OutputsModule, "f") + modules["f"] = createTestInlineModule(ServerRustModule.Output, "f") modules["g"] = createTestInlineModule(modules["f"]!!, "g") - modules["h"] = createTestInlineModule(OutputsModule, "h") + modules["h"] = createTestInlineModule(ServerRustModule.Output, "h") - testProject.withModule(ModelsModule) { + testProject.withModule(ServerRustModule.Model) { testProject.getInlineModuleWriter().withInlineModule(this, modules["a"]!!) { helloWorld(this, "a") } @@ -173,13 +169,13 @@ class RustCrateInlineModuleComposingWriterTest { // Write directly to an inline module without specifying the immediate parent. crate::model::b::c // should have a `hello_world` fn in it now. - testProject.withModule(ModelsModule) { + testProject.withModule(ServerRustModule.Model) { testProject.getInlineModuleWriter().withInlineModuleHierarchy(this, modules["c"]!!) { helloWorld(this, "c") } } // Write to a different top level module to confirm that works. - testProject.withModule(InputsModule) { + testProject.withModule(ServerRustModule.Model) { testProject.getInlineModuleWriter().withInlineModuleHierarchy(this, modules["e"]!!) { helloWorld(this, "e") } @@ -200,12 +196,12 @@ class RustCrateInlineModuleComposingWriterTest { // It should work even if the inner descendent module was added using `withInlineModuleHierarchy` and then // code is added to the intermediate module using `withInlineModuleHierarchyUsingCrate` - testProject.withModule(OutputsModule) { + testProject.withModule(ServerRustModule.Output) { testProject.getInlineModuleWriter().withInlineModuleHierarchy(this, modules["h"]!!) { testProject.getInlineModuleWriter().withInlineModuleHierarchy(this, modules["i"]!!) { helloWorld(this, "i") } - testProject.withModule(ModelsModule) { + testProject.withModule(ServerRustModule.Model) { // While writing to output::h::i, it should be able to a completely different module testProject.getInlineModuleWriter().withInlineModuleHierarchy(this, modules["b"]!!) { rustBlock("pub fn some_other_writer_wrote_this()") { @@ -222,7 +218,7 @@ class RustCrateInlineModuleComposingWriterTest { // Render all of the code. testProject.getInlineModuleWriter().render() - testProject.withModule(ModelsModule) { + testProject.withModule(ServerRustModule.Model) { this.unitTest("test_a") { rust("crate::model::a::hello_world();") rust("crate::model::a::bye_world();") diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt index 98e6dbf7d4..ae974fe2af 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt @@ -74,6 +74,7 @@ class ConstrainedBlobGeneratorTest { ConstrainedBlobGenerator( codegenContext, this.createTestInlineModuleCreator(), + this, constrainedBlobShape, SmithyValidationExceptionConversionGenerator(codegenContext), ).render() @@ -133,6 +134,7 @@ class ConstrainedBlobGeneratorTest { ConstrainedBlobGenerator( codegenContext, writer.createTestInlineModuleCreator(), + writer, constrainedBlobShape, SmithyValidationExceptionConversionGenerator(codegenContext), ).render() diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt index a253296b96..5660ee3fd2 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt @@ -77,6 +77,7 @@ class ConstrainedNumberGeneratorTest { ConstrainedNumberGenerator( codegenContext, this.createTestInlineModuleCreator(), + this, shape, SmithyValidationExceptionConversionGenerator(codegenContext), ).render() @@ -144,6 +145,7 @@ class ConstrainedNumberGeneratorTest { ConstrainedNumberGenerator( codegenContext, writer.createTestInlineModuleCreator(), + writer, constrainedShape, SmithyValidationExceptionConversionGenerator(codegenContext), ).render() diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorTest.kt index 8fef67bbfc..dd7321bf6d 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorTest.kt @@ -10,10 +10,6 @@ import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.implBlock import software.amazon.smithy.rust.codegen.core.smithy.generators.StructureGenerator -import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget -import software.amazon.smithy.rust.codegen.core.smithy.RustCrate -import software.amazon.smithy.rust.codegen.core.smithy.generators.StructureGenerator -import software.amazon.smithy.rust.codegen.core.smithy.generators.implBlock import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt index 61b96a6d66..c9641465f3 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt @@ -17,6 +17,7 @@ import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.lookup import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule +import software.amazon.smithy.rust.codegen.server.smithy.createInlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverRenderWithModelBuilder import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext @@ -54,7 +55,7 @@ class UnconstrainedUnionGeneratorTest { // FZ rebase project.withModule(ServerRustModule.UnconstrainedModule) unconstrainedModuleWriter@{ project.withModule(ServerRustModule.Model) modelsModuleWriter@{ - UnconstrainedUnionGenerator(codegenContext, this@unconstrainedModuleWriter.createInlineModuleCreator(), this@modelsModuleWriter, unionShape).render() + UnconstrainedUnionGenerator(codegenContext, project.createInlineModuleCreator(), this@modelsModuleWriter, unionShape).render() this@unconstrainedModuleWriter.unitTest( name = "unconstrained_union_fail_to_constrain", diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamBaseRequirements.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamBaseRequirements.kt index 46adcc3d7b..d989c0290f 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamBaseRequirements.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamBaseRequirements.kt @@ -116,6 +116,8 @@ abstract class ServerEventStreamBaseRequirements : EventStreamTestRequirements Date: Thu, 16 Feb 2023 00:18:34 +0000 Subject: [PATCH 03/18] Constraints are written to the correct module --- .../ConstraintViolationSymbolProvider.kt | 4 +- .../RustCrateInlineModuleComposingWriter.kt | 47 ++++++++++++++----- ...ustCrateInlineModuleComposingWriterTest.kt | 21 +++++++-- 3 files changed, 54 insertions(+), 18 deletions(-) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt index 30775127b5..0543e48634 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt @@ -107,9 +107,7 @@ class ConstraintViolationSymbolProvider( return RustModule.new( name = name, visibility = visibility, - // FZ rebase - //parent = ServerRustModule.Model, - parent = ServerRustModule.Model, + parent = module, inline = true, documentation = documentation, ) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt index b0081979d2..d3301e8843 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt @@ -131,7 +131,7 @@ private data class InlineModuleWithWriter(val inlineModule : RustModule.LeafModu private val crateToInlineModule: ConcurrentHashMap = ConcurrentHashMap() -class InnerModule(private val debugMode : Boolean) { +class InnerModule(debugMode : Boolean) { private val topLevelModuleWriters: MutableSet = mutableSetOf() private val inlineModuleWriters: HashMap> = hashMapOf() private val docWriters: HashMap> = hashMapOf() @@ -179,10 +179,10 @@ class InnerModule(private val debugMode : Boolean) { rustCrate.withModule(topMost) { var writer = this hierarchy.forEach { - writer = getWriter(writer, it as RustModule.LeafModule) + writer = getWriter(writer, it) } - withInlineModule(writer, bottomMost as RustModule.LeafModule, docWriter, writable) + withInlineModule(writer, bottomMost, docWriter, writable) } } else { check(!bottomMost.isInline()) { @@ -214,10 +214,10 @@ class InnerModule(private val debugMode : Boolean) { // Create an entry in the HashMap for all the descendent modules in the hierarchy. var writer = outerWriter hierarchy.forEach { - writer = getWriter(writer, it as RustModule.LeafModule) + writer = getWriter(writer, it) } - withInlineModule(writer, bottomMost as RustModule.LeafModule, docWriter, writable) + withInlineModule(writer, bottomMost, docWriter, writable) } /** @@ -228,7 +228,7 @@ class InnerModule(private val debugMode : Boolean) { var hierarchy = listOf() while (current is RustModule.LeafModule) { - hierarchy = listOf(current as RustModule.LeafModule) + hierarchy + hierarchy = listOf(current) + hierarchy current = current.parent } @@ -275,7 +275,6 @@ class InnerModule(private val debugMode : Boolean) { * has never been registered before then a new `RustWriter` is created and returned. */ private fun getWriter(outerWriter: RustWriter, inlineModule: RustModule.LeafModule): RustWriter { - // Is this one of our inner writers? val nestedModuleWriter = inlineModuleWriters[outerWriter] if (nestedModuleWriter != null) { return findOrAddToList(nestedModuleWriter, inlineModule) @@ -301,16 +300,42 @@ class InnerModule(private val debugMode : Boolean) { inlineModuleList: MutableList, lookForModule: RustModule.LeafModule ): RustWriter { - val inlineModule = inlineModuleList.firstOrNull() { - it.inlineModule == lookForModule + val inlineModuleAndWriter = inlineModuleList.firstOrNull() { + it.inlineModule.name == lookForModule.name } - return if (inlineModule == null) { + return if (inlineModuleAndWriter == null) { val inlineWriter = createNewInlineModule() inlineModuleList.add(InlineModuleWithWriter(lookForModule, inlineWriter)) inlineWriter } else { - inlineModule.writer + check(inlineModuleAndWriter.inlineModule == lookForModule) { + "the two inline modules have the same name but different attributes on them" + } + + inlineModuleAndWriter.writer + } + } + + private fun combine(inlineModuleWithWriter: InlineModuleWithWriter, inlineModule: RustModule.LeafModule) : InlineModuleWithWriter { + check(inlineModuleWithWriter.inlineModule.name == inlineModule.name) { + "only inline module objects that have the same name can be combined" + } + check(inlineModuleWithWriter.inlineModule.rustMetadata.visibility == inlineModule.rustMetadata.visibility) { + "only inline modules with same visibility can be combined" } + check(inlineModuleWithWriter.inlineModule.inline && inlineModule.inline) { + "both modules need to be inline to be combined together" + } + + val newModule = RustModule.new( + name = inlineModule.name, + parent = inlineModuleWithWriter.inlineModule.parent, + documentation = inlineModuleWithWriter.inlineModule.documentation?.plus("\n")?.plus(inlineModule.documentation) ?: inlineModule.documentation, + visibility = inlineModule.rustMetadata.visibility, + additionalAttributes = inlineModuleWithWriter.inlineModule.rustMetadata.additionalAttributes + inlineModule.rustMetadata.additionalAttributes, + inline = inlineModule.inline + ) + return InlineModuleWithWriter(newModule, inlineModuleWithWriter.writer) } private fun writeDocs(innerModule: RustModule.LeafModule) { diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt index b067a5d123..bca9e7e556 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt @@ -19,7 +19,6 @@ import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestSymbolProvider import java.io.File -import kotlin.collections.Map.Entry class RustCrateInlineModuleComposingWriterTest { private val rustCrate: RustCrate @@ -66,11 +65,11 @@ class RustCrateInlineModuleComposingWriterTest { rustCrate = RustCrate(context.fileManifest, codegenContext.symbolProvider, settings.codegenConfig) } - private fun createTestInlineModule(parentModule: RustModule, moduleName : String) : RustModule.LeafModule = + private fun createTestInlineModule(parentModule: RustModule, moduleName : String, documentation : String? = null) : RustModule.LeafModule = RustModule.new( moduleName, visibility = Visibility.PUBLIC, - documentation = moduleName, + documentation = documentation ?: moduleName, parent = parentModule, inline = true, ) @@ -98,6 +97,13 @@ class RustCrateInlineModuleComposingWriterTest { } } +// private fun extraRustFun(writer: RustWriter, moduleName: String) { +// writer.rustBlock("pub fn extra()") { +// writer.comment("Module $moduleName") +// writer.rust("""println!("extra function defined inside $moduleName");""") +// } +// } + @Test fun `simple inline module works`() { val testProject = TestWorkspace.testProject(serverTestSymbolProvider(model)) @@ -145,6 +151,8 @@ class RustCrateInlineModuleComposingWriterTest { modules["f"] = createTestInlineModule(ServerRustModule.Output, "f") modules["g"] = createTestInlineModule(modules["f"]!!, "g") modules["h"] = createTestInlineModule(ServerRustModule.Output, "h") + // A different kotlin object but would still go in the right place +// val moduleB = createTestInlineModule(ServerRustModule.Model, "b", "A new module") testProject.withModule(ServerRustModule.Model) { testProject.getInlineModuleWriter().withInlineModule(this, modules["a"]!!) { @@ -165,6 +173,10 @@ class RustCrateInlineModuleComposingWriterTest { testProject.getInlineModuleWriter().withInlineModule(this, modules["b"]!!) { byeWorld(this, "b") } + +// testProject.getInlineModuleWriter().withInlineModule(this, moduleB) { +// extraRustFun(this, "b") +// } } // Write directly to an inline module without specifying the immediate parent. crate::model::b::c @@ -175,7 +187,7 @@ class RustCrateInlineModuleComposingWriterTest { } } // Write to a different top level module to confirm that works. - testProject.withModule(ServerRustModule.Model) { + testProject.withModule(ServerRustModule.Input) { testProject.getInlineModuleWriter().withInlineModuleHierarchy(this, modules["e"]!!) { helloWorld(this, "e") } @@ -226,6 +238,7 @@ class RustCrateInlineModuleComposingWriterTest { this.unitTest("test_b") { rust("crate::model::b::hello_world();") rust("crate::model::b::bye_world();") +// rust("crate::model::b::extra();") } this.unitTest("test_someother_writer_wrote") { rust("crate::model::b::some_other_writer_wrote_this();") From 5ef4d563efd45633984cd3b967797b5202b3d0d1 Mon Sep 17 00:00:00 2001 From: Fahad Zubair Date: Thu, 16 Feb 2023 02:24:41 +0000 Subject: [PATCH 04/18] Code generates for non-public constrained types. --- .../smithy/ConstrainedShapeSymbolProvider.kt | 11 +-- .../server/smithy/ServerCodegenVisitor.kt | 68 ------------------- .../UnconstrainedShapeSymbolProvider.kt | 2 - .../ConstrainedCollectionGenerator.kt | 28 ++++---- .../generators/ConstrainedMapGenerator.kt | 2 +- .../smithy/generators/ServerInstantiator.kt | 27 ++++++-- .../smithy/testutil/ServerTestHelpers.kt | 4 -- ...ustCrateInlineModuleComposingWriterTest.kt | 12 ++++ .../ConstrainedBlobGeneratorTest.kt | 9 +-- .../ConstrainedCollectionGeneratorTest.kt | 1 - .../generators/ConstrainedMapGeneratorTest.kt | 1 - .../ConstrainedNumberGeneratorTest.kt | 2 - .../ConstrainedStringGeneratorTest.kt | 4 -- .../generators/ServerBuilderGeneratorTest.kt | 1 - .../generators/ServerInstantiatorTest.kt | 2 +- .../UnconstrainedCollectionGeneratorTest.kt | 3 - .../UnconstrainedMapGeneratorTest.kt | 2 - .../UnconstrainedUnionGeneratorTest.kt | 3 - .../ServerEventStreamBaseRequirements.kt | 1 - 19 files changed, 53 insertions(+), 130 deletions(-) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt index d75f377d0e..57bb1aabe8 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt @@ -68,9 +68,6 @@ class ConstrainedShapeSymbolProvider( private fun publicConstrainedSymbolForMapOrCollectionShape(shape: Shape): Symbol { check(shape is MapShape || shape is CollectionShape) - // FZ rebase - // val rustType = RustType.Opaque(shape.contextName(serviceShape).toPascalCase()) - // return symbolBuilder(shape, rustType).locatedIn(ServerRustModule.Model).build() val (name, module) = getMemberNameAndModule(shape, serviceShape, ServerRustModule.Model, !publicConstrainedTypes) val rustType = RustType.Opaque(name) @@ -123,10 +120,6 @@ class ConstrainedShapeSymbolProvider( is StringShape, is IntegerShape, is ShortShape, is LongShape, is ByteShape, is BlobShape -> { if (shape.isDirectlyConstrained(base)) { - // FZ rebase - //val rustType = RustType.Opaque(shape.contextName(serviceShape).toPascalCase()) - //symbolBuilder(shape, rustType).locatedIn(ServerRustModule.Model).build() - // A standalone constrained shape goes into `ModelsModule`, but one // arising from a constrained member shape goes into a module for the container. val (name, module) = getMemberNameAndModule(shape, serviceShape, ServerRustModule.Model, !publicConstrainedTypes) @@ -179,9 +172,9 @@ class ConstrainedShapeSymbolProvider( // For List, Union and Map, the new shape defined for a constrained member shape // need to be placed into an inline module named `pub {container_name_in_snake_case}` val innerModuleName = RustReservedWords.escapeIfNeeded(container.id.name.toSnakeCase()) + if (pubCrateServerBuilder) { - "_internal" + "_internal" } else { - "" + "" } val innerModule = RustModule.new( diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt index be1447367e..5eeafc14c9 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt @@ -287,9 +287,6 @@ open class ServerCodegenVisitor( ).render(CodegenTarget.SERVER) } - // FZ Rebase mine - // StructureGenerator(model, codegenContext.symbolProvider, this, shape).render(CodegenTarget.SERVER) - renderStructureShapeBuilder(shape, this) } } @@ -301,9 +298,6 @@ open class ServerCodegenVisitor( if (codegenContext.settings.codegenConfig.publicConstrainedTypes || shape.isReachableFromOperationInput()) { val serverBuilderGenerator = ServerBuilderGenerator(codegenContext, shape, validationExceptionConversionGenerator) serverBuilderGenerator.render(rustCrate, writer) - // FZ Rebase mine - // val serverBuilderGenerator = ServerBuilderGenerator(codegenContext, shape) - // serverBuilderGenerator.render(rustCrate, writer) if (codegenContext.settings.codegenConfig.publicConstrainedTypes) { writer.implBlock(codegenContext.symbolProvider.toSymbol(shape)) { @@ -322,16 +316,9 @@ open class ServerCodegenVisitor( } if (!codegenContext.settings.codegenConfig.publicConstrainedTypes) { - // FZ Rebase - // val serverBuilderGeneratorWithoutPublicConstrainedTypes = - // ServerBuilderGeneratorWithoutPublicConstrainedTypes(codegenContext, shape, validationExceptionConversionGenerator) - // serverBuilderGeneratorWithoutPublicConstrainedTypes.render(writer) val serverBuilderGeneratorWithoutPublicConstrainedTypes = ServerBuilderGeneratorWithoutPublicConstrainedTypes(codegenContext, shape, validationExceptionConversionGenerator) serverBuilderGeneratorWithoutPublicConstrainedTypes.render(rustCrate, writer) - // FZ Rebase mine - // ServerBuilderGeneratorWithoutPublicConstrainedTypes(codegenContext, shape) - // serverBuilderGeneratorWithoutPublicConstrainedTypes.render(rustCrate, writer) writer.implBlock(codegenContext.symbolProvider.toSymbol(shape)) { serverBuilderGeneratorWithoutPublicConstrainedTypes.renderConvenienceMethod(this) @@ -352,8 +339,6 @@ open class ServerCodegenVisitor( if (renderUnconstrainedList) { logger.info("[rust-server-codegen] Generating an unconstrained type for collection shape $shape") - // FZ Rebase - // rustCrate.withModule(ServerRustModule.UnconstrainedModule) { rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.UnconstrainedModule, shape, codegenContext) { UnconstrainedCollectionGenerator( codegenContext, @@ -364,10 +349,6 @@ open class ServerCodegenVisitor( if (!isDirectlyConstrained) { logger.info("[rust-server-codegen] Generating a constrained type for collection shape $shape") - // FZ rebase - // rustCrate.withModule(ServerRustModule.ConstrainedModule) { - // PubCrateConstrainedCollectionGenerator(codegenContext, this, shape).render() - rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.ConstrainedModule, shape, codegenContext) { PubCrateConstrainedCollectionGenerator(codegenContext, rustCrate.createInlineModuleCreator(), @@ -378,12 +359,9 @@ open class ServerCodegenVisitor( val constraintsInfo = CollectionTraitInfo.fromShape(shape, codegenContext.constrainedShapeSymbolProvider) if (isDirectlyConstrained) { - // FZ rebase - // rustCrate.withModule(ServerRustModule.Model) { rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.Model, shape, codegenContext) { ConstrainedCollectionGenerator( codegenContext, - // FZ Check? this, shape, constraintsInfo, @@ -393,15 +371,6 @@ open class ServerCodegenVisitor( } if (isDirectlyConstrained || renderUnconstrainedList) { - // FZ rebase - // rustCrate.withModule(ServerRustModule.Model) { - // CollectionConstraintViolationGenerator( - // codegenContext, - // this, - // shape, - // constraintsInfo, - // validationExceptionConversionGenerator, - // ).render() rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.Model, shape, codegenContext) { CollectionConstraintViolationGenerator( codegenContext, @@ -424,9 +393,6 @@ open class ServerCodegenVisitor( if (renderUnconstrainedMap) { logger.info("[rust-server-codegen] Generating an unconstrained type for map $shape") - // FZ rebase - // rustCrate.withModule(ServerRustModule.UnconstrainedModule) { - // UnconstrainedMapGenerator(codegenContext, this, shape).render() rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.UnconstrainedModule, shape, codegenContext) { UnconstrainedMapGenerator(codegenContext, rustCrate.createInlineModuleCreator(), @@ -435,9 +401,6 @@ open class ServerCodegenVisitor( if (!isDirectlyConstrained) { logger.info("[rust-server-codegen] Generating a constrained type for map $shape") - // FZ rebase - // rustCrate.withModule(ServerRustModule.ConstrainedModule) { - // PubCrateConstrainedMapGenerator(codegenContext, this, shape).render() rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.ConstrainedModule, shape, codegenContext) { PubCrateConstrainedMapGenerator(codegenContext, rustCrate.createInlineModuleCreator(), @@ -447,8 +410,6 @@ open class ServerCodegenVisitor( } if (isDirectlyConstrained) { - // FZ rebase - // rustCrate.withModule(ServerRustModule.Model) { rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.Model, shape, codegenContext) { ConstrainedMapGenerator( codegenContext, @@ -461,14 +422,6 @@ open class ServerCodegenVisitor( } if (isDirectlyConstrained || renderUnconstrainedMap) { - // FZ rebase - // rustCrate.withModule(ServerRustModule.Model) { - // MapConstraintViolationGenerator( - // codegenContext, - // this, - // shape, - // validationExceptionConversionGenerator, - // ).render() rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.Model, shape, codegenContext) { MapConstraintViolationGenerator( codegenContext, @@ -498,8 +451,6 @@ open class ServerCodegenVisitor( private fun integralShape(shape: NumberShape) { if (shape.isDirectlyConstrained(codegenContext.symbolProvider)) { logger.info("[rust-server-codegen] Generating a constrained integral $shape") - // FZ Rebase - // rustCrate.withModule(ServerRustModule.Model) { rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.Model, shape, codegenContext) { ConstrainedNumberGenerator(codegenContext, rustCrate.createInlineModuleCreator(), @@ -517,9 +468,6 @@ open class ServerCodegenVisitor( ) { if (shape.hasTrait()) { logger.info("[rust-server-codegen] Generating an enum $shape") - // FZ Rebase - // rustCrate.useShapeWriter(shape) { - // enumShapeGeneratorFactory(codegenContext, shape).render(this) rustCrate.useShapeWriterOrUseWithStructureBuilder(shape, codegenContext) { // Check this? enumShapeGeneratorFactory(codegenContext, shape).render(this) @@ -538,9 +486,6 @@ open class ServerCodegenVisitor( ) } else if (!shape.hasTrait() && shape.isDirectlyConstrained(codegenContext.symbolProvider)) { logger.info("[rust-server-codegen] Generating a constrained string $shape") - // FZ rebase - // rustCrate.withModule(ServerRustModule.Model) { - // ConstrainedStringGenerator(codegenContext, this, shape, validationExceptionConversionGenerator).render() rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.Model, shape, codegenContext) { ConstrainedStringGenerator(codegenContext, rustCrate.createInlineModuleCreator(), @@ -570,16 +515,6 @@ open class ServerCodegenVisitor( ) ) { logger.info("[rust-server-codegen] Generating an unconstrained type for union shape $shape") - // FZ rebase - // rustCrate.withModule(ServerRustModule.UnconstrainedModule) unconstrainedModuleWriter@{ - // rustCrate.withModule(ServerRustModule.Model) modelsModuleWriter@{ - // UnconstrainedUnionGenerator( - // codegenContext, - // this@unconstrainedModuleWriter, - // this@modelsModuleWriter, - // shape, - // ).render() - // } rustCrate.withModule(ServerRustModule.UnconstrainedModule) modelsModuleWriter@{ UnconstrainedUnionGenerator( codegenContext, @@ -634,9 +569,6 @@ open class ServerCodegenVisitor( } if (shape.isDirectlyConstrained(codegenContext.symbolProvider)) { - // FZ rebase - // rustCrate.withModule(ServerRustModule.Model) { - // ConstrainedBlobGenerator(codegenContext, this, shape, validationExceptionConversionGenerator).render() rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.Model, shape, codegenContext) { ConstrainedBlobGenerator(codegenContext, rustCrate.createInlineModuleCreator(), diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProvider.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProvider.kt index e892f1dd15..fc85f3e2b1 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProvider.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProvider.kt @@ -105,8 +105,6 @@ class UnconstrainedShapeSymbolProvider( val module = RustModule.new( RustReservedWords.escapeIfNeeded(name.toSnakeCase()), visibility = Visibility.PUBCRATE, - // FZ rebase - // parent = ServerRustModule.UnconstrainedModule, parent = parent, inline = true, ) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGenerator.kt index 3ae5a78a08..d146f422b0 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGenerator.kt @@ -8,6 +8,7 @@ package software.amazon.smithy.rust.codegen.server.smithy.generators import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.codegen.core.SymbolProvider import software.amazon.smithy.model.shapes.CollectionShape +import software.amazon.smithy.model.shapes.EnumShape import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.model.shapes.UnionShape import software.amazon.smithy.model.traits.LengthTrait @@ -121,23 +122,23 @@ class ConstrainedCollectionGenerator( writer.rustTemplate( """ - impl #{TryFrom}<$inner> for $name { - type Error = #{ConstraintViolation}; + impl #{TryFrom}<$inner> for $name { + type Error = #{ConstraintViolation}; - /// ${rustDocsTryFromMethod(name, inner)} - fn try_from(value: $inner) -> Result { - #{ConstraintChecks:W} + /// ${rustDocsTryFromMethod(name, inner)} + fn try_from(value: $inner) -> Result { + #{ConstraintChecks:W} - Ok(Self(value)) - } + Ok(Self(value)) } + } - impl #{From}<$name> for $inner { - fn from(value: $name) -> Self { - value.into_inner() - } + impl #{From}<$name> for $inner { + fn from(value: $name) -> Self { + value.into_inner() } - """, + } + """, *codegenScope, "ConstraintChecks" to constraintsInfo.map { it.tryFromCheck }.join("\n"), ) @@ -146,7 +147,8 @@ class ConstrainedCollectionGenerator( if (!publicConstrainedTypes && innerShape.canReachConstrainedShape(model, symbolProvider) && innerShape !is StructureShape && - innerShape !is UnionShape + innerShape !is UnionShape && + innerShape !is EnumShape ) { writer.rustTemplate( """ diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGenerator.kt index e5721e7741..7a82dd5e8f 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGenerator.kt @@ -137,7 +137,7 @@ class ConstrainedMapGenerator( value .into_inner() .into_iter() - .map(|(k, v)| (k, v.into())) + .map(|(k, v)| (k.into(), v.into())) .collect() } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiator.kt index 3179b5370e..3d3105f9c7 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiator.kt @@ -16,6 +16,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.generators.Instantiator import software.amazon.smithy.rust.codegen.core.smithy.generators.InstantiatorCustomization import software.amazon.smithy.rust.codegen.core.smithy.generators.InstantiatorSection import software.amazon.smithy.rust.codegen.core.smithy.isOptional +import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.isDirectlyConstrained import software.amazon.smithy.rust.codegen.server.smithy.traits.isReachableFromOperationInput @@ -47,12 +48,26 @@ class ServerBuilderKindBehavior(val codegenContext: CodegenContext) : Instantiat override fun hasFallibleBuilder(shape: StructureShape): Boolean { // Only operation input builders take in unconstrained types. val takesInUnconstrainedTypes = shape.isReachableFromOperationInput() - return ServerBuilderGenerator.hasFallibleBuilder( - shape, - codegenContext.model, - codegenContext.symbolProvider, - takesInUnconstrainedTypes, - ) + + val publicConstrainedTypes = if (codegenContext is ServerCodegenContext) { + codegenContext.settings.codegenConfig.publicConstrainedTypes + } else { + true + } + + return if (publicConstrainedTypes) { + ServerBuilderGenerator.hasFallibleBuilder( + shape, + codegenContext.model, + codegenContext.symbolProvider, + takesInUnconstrainedTypes, + ) + } else { + ServerBuilderGeneratorWithoutPublicConstrainedTypes.hasFallibleBuilder( + shape, + codegenContext.symbolProvider, + ) + } } override fun setterName(memberShape: MemberShape): String = codegenContext.symbolProvider.toMemberName(memberShape) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt index 61f4fc1912..5a1eb90da5 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt @@ -129,10 +129,6 @@ fun StructureShape.serverRenderWithModelBuilder(rustCrate: RustCrate, model: Mod val modelBuilder = ServerBuilderGenerator(serverCodegenContext, this, SmithyValidationExceptionConversionGenerator(serverCodegenContext)) modelBuilder.render(rustCrate, writer) writer.implBlock(symbolProvider.toSymbol(this)) { - // FZ Rebase mine - // val modelBuilder = ServerBuilderGenerator(serverCodegenContext, this) - // modelBuilder.render(rustCrate, writer) - // writer.implBlock(this, symbolProvider) { modelBuilder.renderConvenienceMethod(this) } rustCrate.getInlineModuleWriter().render() diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt index bca9e7e556..a0a9359780 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt @@ -104,6 +104,18 @@ class RustCrateInlineModuleComposingWriterTest { // } // } + @Test + fun `calling withModule multiple times returns same object on rustModule`() { + val testProject = TestWorkspace.testProject(serverTestSymbolProvider(model)) + val writers : MutableSet = mutableSetOf() + testProject.withModule(ServerRustModule.Model) { + writers.add(this) + } + testProject.withModule(ServerRustModule.Model) { + check(writers.contains(this)) + } + } + @Test fun `simple inline module works`() { val testProject = TestWorkspace.testProject(serverTestSymbolProvider(model)) diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt index ae974fe2af..4a09e4d927 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt @@ -70,7 +70,7 @@ class ConstrainedBlobGeneratorTest { project.withModule(ServerRustModule.Model) { addDependency(RuntimeType.blob(codegenContext.runtimeConfig).toSymbol()) - // FZ Rebase + ConstrainedBlobGenerator( codegenContext, this.createTestInlineModuleCreator(), @@ -130,7 +130,6 @@ class ConstrainedBlobGeneratorTest { val writer = RustWriter.forModule(ServerRustModule.Model.name) - // FZ rebase ConstrainedBlobGenerator( codegenContext, writer.createTestInlineModuleCreator(), @@ -139,12 +138,6 @@ class ConstrainedBlobGeneratorTest { SmithyValidationExceptionConversionGenerator(codegenContext), ).render() - // FZ rebase main - // ConstrainedBlobGenerator(codegenContext, - // writer.createTestInlineModuleCreator(), - // writer, - // constrainedBlobShape).render() - // Check that the wrapped type is `pub(crate)`. writer.toString() shouldContain "pub struct ConstrainedBlob(pub(crate) aws_smithy_types::Blob);" } diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt index 5c542faa74..90702c81af 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt @@ -286,7 +286,6 @@ class ConstrainedCollectionGeneratorTest { ) { val constraintsInfo = CollectionTraitInfo.fromShape(constrainedCollectionShape, codegenContext.symbolProvider) ConstrainedCollectionGenerator(codegenContext, writer, constrainedCollectionShape, constraintsInfo).render() - // FZ rebase CollectionConstraintViolationGenerator( codegenContext, writer.createTestInlineModuleCreator(), diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt index c54523fe9f..87b87600a3 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt @@ -155,7 +155,6 @@ class ConstrainedMapGeneratorTest { constrainedMapShape: MapShape, ) { ConstrainedMapGenerator(codegenContext, writer, constrainedMapShape).render() - // FZ rebase MapConstraintViolationGenerator( codegenContext, writer.createTestInlineModuleCreator(), diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt index 5660ee3fd2..1be89ff62d 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt @@ -72,7 +72,6 @@ class ConstrainedNumberGeneratorTest { val project = TestWorkspace.testProject(symbolProvider) - // FZ rebase project.withModule(ServerRustModule.Model) { ConstrainedNumberGenerator( codegenContext, @@ -141,7 +140,6 @@ class ConstrainedNumberGeneratorTest { val codegenContext = serverTestCodegenContext(model) val writer = RustWriter.forModule(ServerRustModule.Model.name) - // FZ rebase ConstrainedNumberGenerator( codegenContext, writer.createTestInlineModuleCreator(), diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt index a736cfe69b..987d402b6b 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt @@ -83,7 +83,6 @@ class ConstrainedStringGeneratorTest { val project = TestWorkspace.testProject(symbolProvider) - // FZ rebase project.withModule(ServerRustModule.Model) { ConstrainedStringGenerator( codegenContext, @@ -145,7 +144,6 @@ class ConstrainedStringGeneratorTest { val writer = RustWriter.forModule(ServerRustModule.Model.name) - // FZ rebase ConstrainedStringGenerator( codegenContext, writer.createTestInlineModuleCreator(), @@ -177,7 +175,6 @@ class ConstrainedStringGeneratorTest { val project = TestWorkspace.testProject(codegenContext.symbolProvider) - // FZ rebase project.withModule(ServerRustModule.Model) { val validationExceptionConversionGenerator = SmithyValidationExceptionConversionGenerator(codegenContext) ConstrainedStringGenerator( @@ -230,7 +227,6 @@ class ConstrainedStringGeneratorTest { val codegenContext = serverTestCodegenContext(model) val project = TestWorkspace.testProject(codegenContext.symbolProvider) - // FZ rebase project.withModule(ServerRustModule.Model) { ConstrainedStringGenerator( codegenContext, diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorTest.kt index dd7321bf6d..68399eb610 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorTest.kt @@ -39,7 +39,6 @@ class ServerBuilderGeneratorTest { val writer = RustWriter.forModule("model") val shape = model.lookup("test#Credentials") - // FZ rebase StructureGenerator(model, codegenContext.symbolProvider, writer, shape, emptyList()).render() val builderGenerator = ServerBuilderGenerator(codegenContext, shape, SmithyValidationExceptionConversionGenerator(codegenContext)) val project = TestWorkspace.testProject() diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiatorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiatorTest.kt index a279966a51..d8191ada69 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiatorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiatorTest.kt @@ -138,7 +138,7 @@ class ServerInstantiatorTest { val data = Node.parse("{}") val project = TestWorkspace.testProject() - // FZ rebase + project.withModule(ServerRustModule.Model) { structure.serverRenderWithModelBuilder(project, model, symbolProvider, this) inner.serverRenderWithModelBuilder(project, model, symbolProvider, this) diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt index 0800f49942..8dd45f0f4f 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt @@ -50,7 +50,6 @@ class UnconstrainedCollectionGeneratorTest { val project = TestWorkspace.testProject(symbolProvider) - // FZ rebase project.withModule(ServerRustModule.Model) { model.lookup("test#StructureC").serverRenderWithModelBuilder(project, model, symbolProvider, this) } @@ -68,12 +67,10 @@ class UnconstrainedCollectionGeneratorTest { listOf(listA, listB).forEach { UnconstrainedCollectionGenerator( codegenContext, - //this@unconstrainedModuleWriter, this@unconstrainedModuleWriter.createTestInlineModuleCreator(), it, ).render() - // FZ rebase CollectionConstraintViolationGenerator( codegenContext, this@modelsModuleWriter.createTestInlineModuleCreator(), diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt index 0478c341da..565c693b36 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt @@ -53,7 +53,6 @@ class UnconstrainedMapGeneratorTest { val project = TestWorkspace.testProject(symbolProvider, debugMode = true) - // FZ rebase project.withModule(Model) { model.lookup("test#StructureC").serverRenderWithModelBuilder(project, model, symbolProvider, this) } @@ -72,7 +71,6 @@ class UnconstrainedMapGeneratorTest { UnconstrainedMapGenerator(codegenContext, this@unconstrainedModuleWriter.createTestInlineModuleCreator(), it).render() - // FZ rebase MapConstraintViolationGenerator( codegenContext, this@modelsModuleWriter.createTestInlineModuleCreator(), diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt index c9641465f3..9981caab04 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt @@ -6,11 +6,9 @@ package software.amazon.smithy.rust.codegen.server.smithy.generators import org.junit.jupiter.api.Test -import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.model.shapes.UnionShape 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.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest @@ -52,7 +50,6 @@ class UnconstrainedUnionGeneratorTest { UnionGenerator(model, symbolProvider, this, unionShape, renderUnknownVariant = false).render() } - // FZ rebase project.withModule(ServerRustModule.UnconstrainedModule) unconstrainedModuleWriter@{ project.withModule(ServerRustModule.Model) modelsModuleWriter@{ UnconstrainedUnionGenerator(codegenContext, project.createInlineModuleCreator(), this@modelsModuleWriter, unionShape).render() diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamBaseRequirements.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamBaseRequirements.kt index d989c0290f..f32cedbbbc 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamBaseRequirements.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamBaseRequirements.kt @@ -76,7 +76,6 @@ abstract class ServerEventStreamBaseRequirements : EventStreamTestRequirements Date: Thu, 16 Feb 2023 11:24:23 +0000 Subject: [PATCH 05/18] Removed a comment --- .../smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt index 5eeafc14c9..0271e5ebdc 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt @@ -469,7 +469,6 @@ open class ServerCodegenVisitor( if (shape.hasTrait()) { logger.info("[rust-server-codegen] Generating an enum $shape") rustCrate.useShapeWriterOrUseWithStructureBuilder(shape, codegenContext) { - // Check this? enumShapeGeneratorFactory(codegenContext, shape).render(this) ConstrainedTraitForEnumGenerator(model, codegenContext.symbolProvider, this, shape).render() } From 0fc4e4c8d8d535dff2ce9cdca9c2cd6dedc1e9fa Mon Sep 17 00:00:00 2001 From: Fahad Zubair Date: Thu, 16 Feb 2023 13:55:11 +0000 Subject: [PATCH 06/18] Using ConcurrentHashmap just to be on the safe side --- .../RustCrateInlineModuleComposingWriter.kt | 47 ++++++------------- 1 file changed, 14 insertions(+), 33 deletions(-) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt index d3301e8843..e0699c4056 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt @@ -12,7 +12,6 @@ import java.util.concurrent.ConcurrentHashMap typealias DocWriter = () -> Any typealias InlineModuleCreator = (Symbol, Writable) -> Unit - /** * Initializes RustCrate -> InnerModule data structure. */ @@ -40,7 +39,7 @@ fun RustCrate.createInlineModuleCreator(): InlineModuleCreator { /** * If the passed in `shape` is a synthetic extracted shape resulting from a constrained struct member, - * the `Writable` is called using the structure's builder module. Otherwise the `Writable` is called + * the `Writable` is called using the structure's builder module. Otherwise, the `Writable` is called * using the given `module`. */ fun RustCrate.withModuleOrWithStructureBuilderModule( @@ -133,8 +132,8 @@ private val crateToInlineModule: ConcurrentHashMap = class InnerModule(debugMode : Boolean) { private val topLevelModuleWriters: MutableSet = mutableSetOf() - private val inlineModuleWriters: HashMap> = hashMapOf() - private val docWriters: HashMap> = hashMapOf() + private val inlineModuleWriters: ConcurrentHashMap> = ConcurrentHashMap() + private val docWriters: ConcurrentHashMap> = ConcurrentHashMap() private val writerCreator = RustWriter.factory(debugMode) private val emptyLineCount: Int = writerCreator .apply("lines-it-always-writes.rs", "crate") @@ -142,13 +141,6 @@ class InnerModule(debugMode : Boolean) { .split("\n")[0] .length - private fun createNewInlineModule(): RustWriter { - val writer = writerCreator.apply("unknown-module-would-never-be-written.rs", "crate") - // There has never been a child of the top most inner module, hence create a new one - inlineModuleWriters[writer] = mutableListOf() - return writer - } - fun withInlineModule(outerWriter: RustWriter, innerModule: RustModule.LeafModule, docWriter: DocWriter? = null, writable: Writable) { if (docWriter != null) { val moduleDocWriterList = docWriters.getOrPut(innerModule) { mutableListOf() } @@ -220,6 +212,17 @@ class InnerModule(debugMode : Boolean) { withInlineModule(writer, bottomMost, docWriter, writable) } + /** + * Creates an in memory writer and registers it with a map of RustWriter -> listOf(Inline descendent modules) + */ + private fun createNewInlineModule(): RustWriter { + val writer = writerCreator.apply("unknown-module-would-never-be-written.rs", "crate") + // Register the new RustWriter in the map to allow further descendent inline modules to be created inside it. + inlineModuleWriters[writer] = mutableListOf() + return writer + } + + /** * Returns the complete hierarchy of a `RustModule.LeafModule` from top to bottom */ @@ -316,28 +319,6 @@ class InnerModule(debugMode : Boolean) { } } - private fun combine(inlineModuleWithWriter: InlineModuleWithWriter, inlineModule: RustModule.LeafModule) : InlineModuleWithWriter { - check(inlineModuleWithWriter.inlineModule.name == inlineModule.name) { - "only inline module objects that have the same name can be combined" - } - check(inlineModuleWithWriter.inlineModule.rustMetadata.visibility == inlineModule.rustMetadata.visibility) { - "only inline modules with same visibility can be combined" - } - check(inlineModuleWithWriter.inlineModule.inline && inlineModule.inline) { - "both modules need to be inline to be combined together" - } - - val newModule = RustModule.new( - name = inlineModule.name, - parent = inlineModuleWithWriter.inlineModule.parent, - documentation = inlineModuleWithWriter.inlineModule.documentation?.plus("\n")?.plus(inlineModule.documentation) ?: inlineModule.documentation, - visibility = inlineModule.rustMetadata.visibility, - additionalAttributes = inlineModuleWithWriter.inlineModule.rustMetadata.additionalAttributes + inlineModule.rustMetadata.additionalAttributes, - inline = inlineModule.inline - ) - return InlineModuleWithWriter(newModule, inlineModuleWithWriter.writer) - } - private fun writeDocs(innerModule: RustModule.LeafModule) { docWriters[innerModule]?.forEach{ it() From aeb3b36f5434b7f9ad413e3f42bdfc04a5b3f721 Mon Sep 17 00:00:00 2001 From: Fahad Zubair Date: Thu, 16 Feb 2023 16:22:46 +0000 Subject: [PATCH 07/18] Clippy warnings removed on constraints, k.into() if gated --- .../CollectionConstraintViolationGenerator.kt | 1 + .../generators/ConstrainedMapGenerator.kt | 12 ++++++++- .../MapConstraintViolationGenerator.kt | 1 + .../ServerBuilderConstraintViolations.kt | 4 ++- .../generators/UnconstrainedUnionGenerator.kt | 4 ++- .../ConstrainedMemberTransform.kt | 25 ++++++++----------- 6 files changed, 30 insertions(+), 17 deletions(-) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/CollectionConstraintViolationGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/CollectionConstraintViolationGenerator.kt index 1219b981ae..930165648c 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/CollectionConstraintViolationGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/CollectionConstraintViolationGenerator.kt @@ -77,6 +77,7 @@ class CollectionConstraintViolationGenerator( // and is for use by the framework. rustTemplate( """ + ##[allow(clippy::enum_variant_names)] ##[derive(Debug, PartialEq)] ${constraintViolationVisibility.toRustQualifier()} enum $constraintViolationName { #{ConstraintViolationVariants:W} diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGenerator.kt index 7a82dd5e8f..28b0d9f8d7 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGenerator.kt @@ -7,6 +7,7 @@ package software.amazon.smithy.rust.codegen.server.smithy.generators import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.shapes.MapShape +import software.amazon.smithy.model.shapes.StringShape import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.model.shapes.UnionShape import software.amazon.smithy.model.traits.LengthTrait @@ -21,6 +22,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.expectRustMetadata import software.amazon.smithy.rust.codegen.core.util.expectTrait import software.amazon.smithy.rust.codegen.server.smithy.PubCrateConstraintViolationSymbolProvider import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext +import software.amazon.smithy.rust.codegen.server.smithy.typeNameContainsNonPublicType /** * [ConstrainedMapGenerator] generates a wrapper tuple newtype holding a constrained `std::collections::HashMap`. @@ -130,6 +132,14 @@ class ConstrainedMapGenerator( valueShape !is StructureShape && valueShape !is UnionShape ) { + val keyShape = model.expectShape(shape.key.target, StringShape::class.java) + val keyNeedsConversion = keyShape.typeNameContainsNonPublicType(model, symbolProvider, publicConstrainedTypes) + val key = if (keyNeedsConversion) { + "k.into()" + } else { + "k" + } + writer.rustTemplate( """ impl #{From}<$name> for #{FullyUnconstrainedSymbol} { @@ -137,7 +147,7 @@ class ConstrainedMapGenerator( value .into_inner() .into_iter() - .map(|(k, v)| (k.into(), v.into())) + .map(|(k, v)| ($key, v.into())) .collect() } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/MapConstraintViolationGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/MapConstraintViolationGenerator.kt index 51c156d0f3..c65e6c38ca 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/MapConstraintViolationGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/MapConstraintViolationGenerator.kt @@ -76,6 +76,7 @@ class MapConstraintViolationGenerator( // and is for use by the framework. rustTemplate( """ + ##[allow(clippy::enum_variant_names)] ##[derive(Debug, PartialEq)] pub${ if (constraintViolationVisibility == Visibility.PUBCRATE) " (crate) " else "" } enum $constraintViolationName { ${if (shape.hasTrait()) "Length(usize)," else ""} diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderConstraintViolations.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderConstraintViolations.kt index bd968bb1b7..50659f0d9e 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderConstraintViolations.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderConstraintViolations.kt @@ -71,7 +71,9 @@ class ServerBuilderConstraintViolations( writer.docs("Holds one variant for each of the ways the builder can fail.") if (nonExhaustive) Attribute.NonExhaustive.render(writer) val constraintViolationSymbolName = constraintViolationSymbolProvider.toSymbol(shape).name - writer.rustBlock("pub${if (visibility == Visibility.PUBCRATE) " (crate) " else ""} enum $constraintViolationSymbolName") { + writer.rustBlock(""" + ##[allow(clippy::enum_variant_names)] + pub${if (visibility == Visibility.PUBCRATE) " (crate) " else ""} enum $constraintViolationSymbolName""") { renderConstraintViolations(writer) } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGenerator.kt index 6b7b1ff911..e599836eee 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGenerator.kt @@ -139,7 +139,9 @@ class UnconstrainedUnionGenerator( constraintViolationSymbol ) { Attribute(derive(RuntimeType.Debug, RuntimeType.PartialEq)).render(this) - rustBlock("pub${if (constraintViolationVisibility == Visibility.PUBCRATE) " (crate)" else ""} enum $constraintViolationName") { + rustBlock(""" + ##[allow(clippy::enum_variant_names)] + pub${if (constraintViolationVisibility == Visibility.PUBCRATE) " (crate)" else ""} enum $constraintViolationName""") { constraintViolations().forEach { renderConstraintViolation(this, it) } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/transformers/ConstrainedMemberTransform.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/transformers/ConstrainedMemberTransform.kt index 1ae50a06ac..a32af8ce78 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/transformers/ConstrainedMemberTransform.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/transformers/ConstrainedMemberTransform.kt @@ -22,7 +22,6 @@ import java.util.* import software.amazon.smithy.rust.codegen.core.util.UNREACHABLE import software.amazon.smithy.rust.codegen.core.util.orNull import software.amazon.smithy.rust.codegen.server.smithy.allConstraintTraits -import software.amazon.smithy.rust.codegen.server.smithy.transformers.ConstrainedMemberTransform.makeNonConstrained /** * Transforms all member shapes that have constraints on them into equivalent non-constrained @@ -86,10 +85,8 @@ object ConstrainedMemberTransform { .flatMap { it.constrainedMembers() } .mapNotNull { val transformation = it.makeNonConstrained(model, additionalNames) - if (transformation != null) { - // Keep record of new names that have been generated to ensure none of them regenerated. - additionalNames.add(transformation.newShape.id) - } + // Keep record of new names that have been generated to ensure none of them regenerated. + additionalNames.add(transformation.newShape.id) transformation } @@ -169,31 +166,31 @@ object ConstrainedMemberTransform { private fun MemberShape.makeNonConstrained( model: Model, additionalNames: MutableSet, - ): MemberShapeTransformation? { - val (constraintTraits, otherTraits) = this.allTraits.values + ): MemberShapeTransformation { + val (memberConstraintTraits, otherTraits) = this.allTraits.values .partition { memberConstraintTraitsToOverride.contains(it.javaClass) } - // No transformation required in case the member shape has no constraints. - if (constraintTraits.isEmpty()) - return null + check(memberConstraintTraits.isNotEmpty()) { + "There must at least be one member constraint on the shape" + } // Build a new shape similar to the target of the constrained member shape. It should // have all of the original constraints that have not been overridden, and the ones // that this member shape overrides. val targetShape = model.expectShape(this.target) if (targetShape !is ToSmithyBuilder<*>) - UNREACHABLE("member target shapes will always be buildable") + UNREACHABLE("Member target shapes will always be buildable") return when (val builder = targetShape.toBuilder()) { is AbstractShapeBuilder<*, *> -> { // Use the target builder to create a new standalone shape that would // be added to the model later on. Keep all existing traits on the target // but replace the ones that are overridden on the member shape. - val nonOverriddenTraitsOnTarget = + val nonOverriddenConstraintTraits = builder.allTraits.values.filter { existingTrait -> - constraintTraits.none { it.toShapeId() == existingTrait.toShapeId() } + memberConstraintTraits.none { it.toShapeId() == existingTrait.toShapeId() } } // Add a synthetic constraint on all new shapes being defined, that would link @@ -203,7 +200,7 @@ object ConstrainedMemberTransform { // Combine target traits, overridden traits and the synthetic trait val newTraits = - nonOverriddenTraitsOnTarget + constraintTraits + syntheticTrait + nonOverriddenConstraintTraits + memberConstraintTraits + syntheticTrait // Create a new unique standalone shape that will be added to the model later on val shapeId = overriddenShapeId(model, additionalNames, this.id) From c92e4b6ec9a1647ee9204273d79e9e074b86961b Mon Sep 17 00:00:00 2001 From: Fahad Zubair Date: Thu, 16 Feb 2023 16:29:42 +0000 Subject: [PATCH 08/18] Wordings for some of the checks changed --- .../smithy/rust/codegen/server/smithy/Constraints.kt | 3 +-- .../smithy/RustCrateInlineModuleComposingWriter.kt | 10 +++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt index 98ecb95a70..d6a1f88eb6 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt @@ -186,7 +186,6 @@ fun Shape.overriddenConstrainedMemberInfo(): Pair? { * Returns the parent and the inline module that this particular shape should go in. */ fun Shape.getParentAndInlineModuleForConstrainedMember(symbolProvider: SymbolProvider, pubCrateServerBuilder: Boolean): Pair? { - //val container = overriddenConstrainedMemberInfo()?.first ?: return null val overriddenTrait = getTrait() ?: return null return if (overriddenTrait.container is StructureShape) { val structureModule = symbolProvider.toSymbol(overriddenTrait.container).module() @@ -201,7 +200,7 @@ fun Shape.getParentAndInlineModuleForConstrainedMember(symbolProvider: SymbolPro val shapeSymbol = symbolProvider.toSymbol(this) val shapeModule = shapeSymbol.module() check(!shapeModule.parent.isInline()) { - "parent module of $id should not be an inline module" + "Parent module of $id should not be an inline module" } Pair(shapeModule.parent as RustModule.LeafModule, shapeModule) } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt index e0699c4056..59800c0ae5 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt @@ -67,7 +67,7 @@ fun RustCrate.withModuleOrWithStructureBuilderModule( /** * If the passed in `shape` is a synthetic extracted shape resulting from a constrained struct member, - * the `Writable` is called using the structure's builder module. Otherwise the `Writable` is called + * the `Writable` is called using the structure's builder module. Otherwise, the `Writable` is called * using shape's `module`. */ fun RustCrate.useShapeWriterOrUseWithStructureBuilder( @@ -104,7 +104,7 @@ fun RustCrate.withInMemoryInlineModule( codeWritable: Writable, ) { check(inlineModule.isInline()) { - "module has to be an inline module for it to be used with the InlineModuleWriter" + "Module has to be an inline module for it to be used with the InlineModuleWriter" } this.getInlineModuleWriter().withInlineModuleHierarchy(outerWriter, inlineModule, docWriter) { codeWritable(this) @@ -155,7 +155,7 @@ class InnerModule(debugMode : Boolean) { fun withInlineModuleHierarchyUsingCrate(rustCrate: RustCrate, inlineModule: RustModule.LeafModule, docWriter: DocWriter? = null, writable: Writable) { val hierarchy = getHierarchy(inlineModule).toMutableList() check(!hierarchy.first().isInline()) { - "when adding a `RustModule.LeafModule` to the crate, the topmost module in the hierarchy cannot be an inline module" + "When adding a `RustModule.LeafModule` to the crate, the topmost module in the hierarchy cannot be an inline module." } // The last in the hierarchy is the one we will return the writer for. val bottomMost = hierarchy.removeLast() @@ -178,7 +178,7 @@ class InnerModule(debugMode : Boolean) { } } else { check(!bottomMost.isInline()) { - "there is only one module in hierarchy so it has to be non-inlined" + "There is only one module in the hierarchy, so it has to be non-inlined." } rustCrate.withModule(bottomMost) { registerTopMostWriter(this) @@ -197,7 +197,7 @@ class InnerModule(debugMode : Boolean) { hierarchy.removeFirst() } check(hierarchy.isNotEmpty()) { - "an inline module should always have one parent besides itself" + "An inline module should always have one parent besides itself." } // The last in the hierarchy is the module under which the new inline module resides. From 765ff9d3d41ae6ddd05405c5b2135f81f29645a2 Mon Sep 17 00:00:00 2001 From: Fahad Zubair Date: Fri, 17 Feb 2023 15:16:37 +0000 Subject: [PATCH 09/18] Test need to call rustCrate.renderInlineMemoryModules --- ...lientEventStreamMarshallerGeneratorTest.kt | 3 +- ...entEventStreamUnmarshallerGeneratorTest.kt | 3 +- .../core/testutil/EventStreamTestTools.kt | 17 +++-- .../smithy/ConstrainedShapeSymbolProvider.kt | 19 ++--- .../RustCrateInlineModuleComposingWriter.kt | 23 +++++-- .../server/smithy/ServerCodegenVisitor.kt | 1 - .../SmithyValidationExceptionDecorator.kt | 8 +-- .../generators/ConstrainedBlobGenerator.kt | 3 +- .../generators/ServerBuilderGenerator.kt | 3 +- .../generators/UnconstrainedUnionGenerator.kt | 5 +- .../smithy/testutil/ServerTestHelpers.kt | 1 - .../ConstrainedMemberTransform.kt | 3 +- .../ConstrainedShapeSymbolProviderTest.kt | 2 +- .../smithy/ConstraintsMemberShapeTest.kt | 69 ++++++++++--------- ...ustCrateInlineModuleComposingWriterTest.kt | 17 +---- .../ServerBuilderDefaultValuesTest.kt | 2 + .../generators/ServerBuilderGeneratorTest.kt | 42 +++++++---- .../generators/ServerInstantiatorTest.kt | 2 + .../ServerOperationErrorGeneratorTest.kt | 3 +- .../UnconstrainedCollectionGeneratorTest.kt | 2 + .../UnconstrainedMapGeneratorTest.kt | 4 +- .../UnconstrainedUnionGeneratorTest.kt | 2 + .../ServerEventStreamBaseRequirements.kt | 5 +- ...erverEventStreamMarshallerGeneratorTest.kt | 6 +- ...verEventStreamUnmarshallerGeneratorTest.kt | 7 +- 25 files changed, 147 insertions(+), 105 deletions(-) diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamMarshallerGeneratorTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamMarshallerGeneratorTest.kt index 936d3b6324..6249be524a 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamMarshallerGeneratorTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamMarshallerGeneratorTest.kt @@ -17,6 +17,7 @@ import software.amazon.smithy.rust.codegen.core.testutil.EventStreamTestTools import software.amazon.smithy.rust.codegen.core.testutil.EventStreamTestVariety import software.amazon.smithy.rust.codegen.core.testutil.TestEventStreamProject import software.amazon.smithy.rust.codegen.core.testutil.TestRuntimeConfig +import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest class ClientEventStreamMarshallerGeneratorTest { @ParameterizedTest @@ -41,6 +42,6 @@ class ClientEventStreamMarshallerGeneratorTest { }, CodegenTarget.CLIENT, EventStreamTestVariety.Marshall, - ) + ).compileAndTest() } } diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamUnmarshallerGeneratorTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamUnmarshallerGeneratorTest.kt index f9be7b3bf4..f505747af7 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamUnmarshallerGeneratorTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamUnmarshallerGeneratorTest.kt @@ -19,6 +19,7 @@ import software.amazon.smithy.rust.codegen.core.testutil.EventStreamTestModels import software.amazon.smithy.rust.codegen.core.testutil.EventStreamTestTools import software.amazon.smithy.rust.codegen.core.testutil.EventStreamTestVariety import software.amazon.smithy.rust.codegen.core.testutil.TestEventStreamProject +import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest class ClientEventStreamUnmarshallerGeneratorTest { @ParameterizedTest @@ -44,6 +45,6 @@ class ClientEventStreamUnmarshallerGeneratorTest { }, CodegenTarget.CLIENT, EventStreamTestVariety.Unmarshall, - ) + ).compileAndTest() } } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamTestTools.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamTestTools.kt index 567ff8b61b..8c6e2da440 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamTestTools.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamTestTools.kt @@ -78,7 +78,7 @@ interface EventStreamTestRequirements { ) /** Render an error struct and builder */ - fun renderError(writer: RustWriter, codegenContext: C, shape: StructureShape) + fun renderError(rustCrate: RustCrate, writer: RustWriter, codegenContext: C, shape: StructureShape) } object EventStreamTestTools { @@ -87,8 +87,12 @@ object EventStreamTestTools { requirements: EventStreamTestRequirements, codegenTarget: CodegenTarget, variety: EventStreamTestVariety, - ) { - val model = EventStreamNormalizer.transform(OperationNormalizer.transform(testCase.model)) + transformers: List<(Model)->Model> = listOf() + ) : TestWriterDelegator { + val model = (listOf(OperationNormalizer::transform, EventStreamNormalizer::transform) + transformers).fold (testCase.model) { model, transformer -> + transformer(model) + } + val serviceShape = model.expectShape(ShapeId.from("test#TestService")) as ServiceShape val codegenContext = requirements.createCodegenContext( model, @@ -106,7 +110,10 @@ object EventStreamTestTools { EventStreamTestVariety.Unmarshall -> writeUnmarshallTestCases(testCase, codegenTarget, generator) } } - test.project.compileAndTest() + + println(testCase.model.toString()) + + return test.project } private fun generateTestProject( @@ -130,7 +137,7 @@ object EventStreamTestTools { requirements.renderOperationError(this, model, symbolProvider, operationShape) requirements.renderOperationError(this, model, symbolProvider, unionShape) for (shape in errors) { - requirements.renderError(this, codegenContext, shape) + requirements.renderError(project,this, codegenContext, shape) } } val inputOutput = model.lookup("test#TestStreamInputOutput") diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt index 57bb1aabe8..cfc55fc3e0 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt @@ -33,11 +33,13 @@ import software.amazon.smithy.rust.codegen.core.smithy.handleRustBoxing import software.amazon.smithy.rust.codegen.core.smithy.locatedIn import software.amazon.smithy.rust.codegen.core.smithy.rustType import software.amazon.smithy.rust.codegen.core.smithy.symbolBuilder +import software.amazon.smithy.rust.codegen.core.util.getTrait import software.amazon.smithy.rust.codegen.core.util.hasTrait import software.amazon.smithy.rust.codegen.core.util.orNull import software.amazon.smithy.rust.codegen.core.util.toPascalCase import software.amazon.smithy.rust.codegen.core.util.toSnakeCase import software.amazon.smithy.rust.codegen.server.smithy.generators.serverBuilderModule +import software.amazon.smithy.rust.codegen.server.smithy.traits.SyntheticStructureFromConstrainedMemberTrait /** * The [ConstrainedShapeSymbolProvider] returns, for a given _directly_ @@ -62,7 +64,7 @@ class ConstrainedShapeSymbolProvider( private val base: RustSymbolProvider, private val model: Model, private val serviceShape: ServiceShape, - private val publicConstrainedTypes : Boolean = true + private val publicConstrainedTypes: Boolean ) : WrappingSymbolProvider(base) { private val nullableIndex = NullableIndex.of(model) @@ -161,17 +163,18 @@ class ConstrainedShapeSymbolProvider( defaultModule: RustModule.LeafModule, pubCrateServerBuilder: Boolean, ): Pair { - val (container, member) = - shape.overriddenConstrainedMemberInfo() ?: return Pair(shape.contextName(serviceShape), defaultModule) + val syntheticMemberTrait = shape.getTrait() + ?: return Pair(shape.contextName(serviceShape), defaultModule) - return if (container is StructureShape) { - val builderModule = container.serverBuilderModule(base, pubCrateServerBuilder) - val renameTo = member.memberName ?: member.id.name + return if (syntheticMemberTrait.container is StructureShape) { + val builderModule = syntheticMemberTrait.container.serverBuilderModule(base, pubCrateServerBuilder) + val renameTo = syntheticMemberTrait.member.memberName ?: syntheticMemberTrait.member.id.name Pair(renameTo.toPascalCase(), builderModule) } else { // For List, Union and Map, the new shape defined for a constrained member shape // need to be placed into an inline module named `pub {container_name_in_snake_case}` - val innerModuleName = RustReservedWords.escapeIfNeeded(container.id.name.toSnakeCase()) + if (pubCrateServerBuilder) { + val moduleName = RustReservedWords.escapeIfNeeded(syntheticMemberTrait.container.id.name.toSnakeCase()) + val innerModuleName = moduleName + if (pubCrateServerBuilder) { "_internal" } else { "" @@ -183,7 +186,7 @@ class ConstrainedShapeSymbolProvider( parent = defaultModule, inline = true, ) - val renameTo = member.memberName ?: member.id.name + val renameTo = syntheticMemberTrait.member.memberName ?: syntheticMemberTrait.member.id.name Pair(renameTo.toPascalCase(), innerModule) } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt index 59800c0ae5..6e8fefa0c1 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt @@ -94,6 +94,14 @@ fun RustCrate.useShapeWriterOrUseWithStructureBuilder( } } + +fun RustCrate.renderInlineMemoryModules() { + val inlineModule = crateToInlineModule[this] + check(inlineModule != null) { + "InlineModule writer has not been registered for this crate" + } + inlineModule.render() +} /** * Given a `RustWriter` calls the `Writable` using a `RustWriter` for the `inlineModule` */ @@ -243,6 +251,8 @@ class InnerModule(debugMode : Boolean) { * Writes out each inline module's code (`toString`) to the respective top level `RustWriter`. */ fun render() { + var writerToAddDependencies : RustWriter? = null + fun writeInlineCode(rustWriter: RustWriter, code: String) { val inlineCode = code.drop(emptyLineCount) rustWriter.writeWithNoFormatting(inlineCode) @@ -250,7 +260,7 @@ class InnerModule(debugMode : Boolean) { fun renderDescendents(topLevelWriter: RustWriter, inMemoryWriter: RustWriter) { // Traverse all descendent inline modules and render them. - inlineModuleWriters[inMemoryWriter]?.forEach { + inlineModuleWriters[inMemoryWriter]!!.forEach { writeDocs(it.inlineModule) topLevelWriter.withInlineModule(it.inlineModule) { @@ -259,17 +269,20 @@ class InnerModule(debugMode : Boolean) { } // Add dependencies introduced by the inline module to the - it.writer.dependencies.forEach { dep -> topLevelWriter.addDependency(dep) } + it.writer.dependencies.forEach { dep -> writerToAddDependencies!!.addDependency(dep) } } } // Go over all the top level modules, create an `inlineModule` on the `RustWriter` // and call the descendent hierarchy renderer using the `inlineModule::RustWriter` topLevelModuleWriters.forEach { - val inlineModuleWithWriter = inlineModuleWriters[it] - if (inlineModuleWithWriter != null) { - renderDescendents(it, it) + writerToAddDependencies = it + + check(inlineModuleWriters[it] != null) { + "There must be a registered RustWriter for this module" } + + renderDescendents(it, it) } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt index 0271e5ebdc..bcaaa33cd3 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt @@ -413,7 +413,6 @@ open class ServerCodegenVisitor( rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.Model, shape, codegenContext) { ConstrainedMapGenerator( codegenContext, - // check? this, shape, if (renderUnconstrainedMap) codegenContext.unconstrainedShapeSymbolProvider.toSymbol(shape) else null, diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/SmithyValidationExceptionDecorator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/SmithyValidationExceptionDecorator.kt index eb91206b5e..7d6d3eb9c8 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/SmithyValidationExceptionDecorator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/SmithyValidationExceptionDecorator.kt @@ -141,8 +141,7 @@ class SmithyValidationExceptionConversionGenerator(private val codegenContext: S Self::Length(length) => crate::model::ValidationExceptionField { message: format!("${it.validationErrorMessage()}", length, &path), path, - }, - """, + },""", ) } if (isKeyConstrained(keyShape, symbolProvider)) { @@ -217,8 +216,7 @@ class SmithyValidationExceptionConversionGenerator(private val codegenContext: S if (isMemberConstrained) { validationExceptionFields += { rust( - """ - Self::Member(index, member_constraint_violation) => + """Self::Member(index, member_constraint_violation) => member_constraint_violation.as_validation_exception_field(path + "/" + &index.to_string()) """, ) @@ -233,7 +231,7 @@ class SmithyValidationExceptionConversionGenerator(private val codegenContext: S } """, "String" to RuntimeType.String, - "AsValidationExceptionFields" to validationExceptionFields.join("\n"), + "AsValidationExceptionFields" to validationExceptionFields.join(""), ) } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGenerator.kt index 455a000470..76770b52d2 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGenerator.kt @@ -154,8 +154,7 @@ data class BlobLength(val lengthTrait: LengthTrait) { Self::Length(length) => crate::model::ValidationExceptionField { message: format!("${lengthTrait.validationErrorMessage()}", length, &path), path, - }, - """, + },""", ) }, this::renderValidationFunction, diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGenerator.kt index 3a36be1861..8b1d8c944a 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGenerator.kt @@ -571,8 +571,7 @@ class ServerBuilderGenerator( writer.rustTemplate( """ .map(|res| - res${if (constrainedTypeHoldsFinalType(member)) "" else ".map(|v| v.into())"} - ${if (errHasBox) ".map_err(Box::new)" else "" } + res${if (constrainedTypeHoldsFinalType(member)) "" else ".map(|v| v.into())"} ${if (errHasBox) ".map_err(Box::new)" else "" } .map_err(ConstraintViolation::${constraintViolation.name()}) ) .transpose()? diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGenerator.kt index e599836eee..a6d14653e6 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGenerator.kt @@ -135,7 +135,6 @@ class UnconstrainedUnionGenerator( } inlineModuleCreator( - //constraintViolationSymbol.module(), codegenContext constraintViolationSymbol ) { Attribute(derive(RuntimeType.Debug, RuntimeType.PartialEq)).render(this) @@ -227,9 +226,7 @@ class UnconstrainedUnionGenerator( """ { let constrained: #{ConstrainedSymbol} = $unconstrainedVar - .try_into() - $boxIt - $boxErr + .try_into() $boxIt $boxErr .map_err(Self::Error::${ConstraintViolation(member).name()})?; constrained.into() } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt index 5a1eb90da5..452d7860c9 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt @@ -131,5 +131,4 @@ fun StructureShape.serverRenderWithModelBuilder(rustCrate: RustCrate, model: Mod writer.implBlock(symbolProvider.toSymbol(this)) { modelBuilder.renderConvenienceMethod(this) } - rustCrate.getInlineModuleWriter().render() } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/transformers/ConstrainedMemberTransform.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/transformers/ConstrainedMemberTransform.kt index a32af8ce78..04963ab5a0 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/transformers/ConstrainedMemberTransform.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/transformers/ConstrainedMemberTransform.kt @@ -21,6 +21,7 @@ import java.lang.IllegalStateException import java.util.* import software.amazon.smithy.rust.codegen.core.util.UNREACHABLE import software.amazon.smithy.rust.codegen.core.util.orNull +import software.amazon.smithy.rust.codegen.core.util.orNullIfEmpty import software.amazon.smithy.rust.codegen.server.smithy.allConstraintTraits /** @@ -77,7 +78,7 @@ object ConstrainedMemberTransform { // The transformer will add new shapes, and will replace existing member shapes' target // with the newly added shapes. val transformations = model.operationShapes - .flatMap { listOfNotNull(it.input.orNull(), it.output.orNull()) } + .flatMap { listOfNotNull(it.input.orNull(), it.output.orNull()) + it.errors } .mapNotNull { model.expectShape(it).asStructureShape().orElse(null) } .filter { it.hasTrait(SyntheticInputTrait.ID) || it.hasTrait(SyntheticOutputTrait.ID) } .flatMap { walker.walkShapes(it) } diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProviderTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProviderTest.kt index d96c761fa8..39a4146351 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProviderTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProviderTest.kt @@ -90,7 +90,7 @@ class ConstrainedShapeSymbolProviderTest { private val model = baseModelString.asSmithyModel() private val serviceShape = model.lookup("test#TestService") private val symbolProvider = serverTestSymbolProvider(model, serviceShape) - private val constrainedShapeSymbolProvider = ConstrainedShapeSymbolProvider(symbolProvider, model, serviceShape) + private val constrainedShapeSymbolProvider = ConstrainedShapeSymbolProvider(symbolProvider, model, serviceShape, true) companion object { @JvmStatic diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt index 3ae0383b06..f10b5d7473 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt @@ -1,21 +1,21 @@ package software.amazon.smithy.rust.codegen.server.smithy +import io.kotest.matchers.collections.shouldContain +import io.kotest.matchers.shouldBe +import io.kotest.matchers.shouldNotBe import org.junit.jupiter.api.Test -import software.amazon.smithy.codegen.core.ReservedWordSymbolProvider import software.amazon.smithy.model.Model import software.amazon.smithy.model.shapes.ShapeId import software.amazon.smithy.model.traits.RequiredTrait 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.smithy.DirectedWalker import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.server.smithy.transformers.ConstrainedMemberTransform import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig import software.amazon.smithy.rust.codegen.core.smithy.RuntimeCrateLocation import software.amazon.smithy.rust.codegen.core.smithy.RustCrate import software.amazon.smithy.rust.codegen.core.smithy.transformers.OperationNormalizer -import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.generatePluginContext import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.runCommand @@ -26,11 +26,8 @@ import software.amazon.smithy.rust.codegen.server.smithy.customizations.ServerRe import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionDecorator import software.amazon.smithy.rust.codegen.server.smithy.customize.CombinedServerCodegenDecorator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext -import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestSymbolProvider import java.io.File import java.nio.file.Path -import java.util.logging.Level -import java.util.logging.Logger class ConstraintsMemberShapeTest { private val outputModelOnly = """ @@ -276,8 +273,13 @@ class ConstraintsMemberShapeTest { runtimeConfig = runtimeConfig, overrideTestDir = dirToUse, ) - val codegenDecorator: CombinedServerCodegenDecorator = - CombinedServerCodegenDecorator.fromClasspath(context) + val codegenDecorator = + CombinedServerCodegenDecorator.fromClasspath( + context, + ServerRequiredCustomizations(), + SmithyValidationExceptionDecorator(), + CustomValidationExceptionWithReasonDecorator(), + ) ServerCodegenVisitor(context, codegenDecorator) .execute() @@ -383,46 +385,49 @@ class ConstraintsMemberShapeTest { lazyMessage: () -> Any = ::defaultError, ) { val memberId = ShapeId.from(member) - check(model.getShape(memberId).isPresent, lazyMessage) + assert(model.getShape(memberId).isPresent) { lazyMessage } + val memberShape = model.expectShape(memberId).asMemberShape().get() val memberTargetShape = model.expectShape(memberShape.target) val orgMemberId = ShapeId.from(orgModelMember) - check(baseModel.getShape(orgMemberId).isPresent, lazyMessage) - val originalShape = baseModel.expectShape(orgMemberId).asMemberShape().get() - val originalTargetShape = model.expectShape(originalShape.target) + assert(baseModel.getShape(orgMemberId).isPresent) { lazyMessage } + + val beforeTransformMemberShape = baseModel.expectShape(orgMemberId).asMemberShape().get() + val originalTargetShape = model.expectShape(beforeTransformMemberShape.target) val extractableConstraintTraits = allConstraintTraits - RequiredTrait::class.java // New member shape should not have the overridden constraints on it - check(!extractableConstraintTraits.any(memberShape::hasTrait), lazyMessage) + assert(!extractableConstraintTraits.any(memberShape::hasTrait)) { lazyMessage } // Target shape has to be changed to a new shape - check(memberTargetShape.id.name != originalShape.target.name, lazyMessage) + memberTargetShape.id.name shouldNotBe beforeTransformMemberShape.target.name + // Target shape's name should match the expected name val expectedName = memberShape.container.name.substringAfter('#') + memberShape.memberName.substringBefore('#').toPascalCase() - check(memberTargetShape.id.name == expectedName, lazyMessage) - // New shape should have all of the constraint traits that were on the member shape, + + memberTargetShape.id.name shouldBe expectedName + + // New shape should have all the constraint traits that were on the member shape, // and it should also have the traits that the target type contains. - val originalConstrainedTraits = - originalShape.allTraits.values.filter { allConstraintTraits.contains(it.javaClass) }.toSet() + val beforeTransformConstraintTraits = + beforeTransformMemberShape.allTraits.values.filter { allConstraintTraits.contains(it.javaClass) }.toSet() val newShapeConstrainedTraits = memberTargetShape.allTraits.values.filter { allConstraintTraits.contains(it.javaClass) }.toSet() - val leftOutConstraintTrait = originalConstrainedTraits - newShapeConstrainedTraits - check( + val leftOutConstraintTrait = beforeTransformConstraintTraits - newShapeConstrainedTraits + assert( leftOutConstraintTrait.isEmpty() || leftOutConstraintTrait.all { it.toShapeId() == RequiredTrait.ID - }, - lazyMessage, - ) + },) { lazyMessage } // In case the target shape has some more constraints, which the member shape did not override, // then those still need to apply on the new standalone shape that has been defined. val leftOverTraits = originalTargetShape.allTraits.values - .filter { beforeOverridingTrait -> originalConstrainedTraits.none { beforeOverridingTrait.toShapeId() == it.toShapeId() } } + .filter { beforeOverridingTrait -> beforeTransformConstraintTraits.none { beforeOverridingTrait.toShapeId() == it.toShapeId() } } val allNewShapeTraits = memberTargetShape.allTraits.values.toList() - check((leftOverTraits + newShapeConstrainedTraits).all { it in allNewShapeTraits }, lazyMessage) + assert((leftOverTraits + newShapeConstrainedTraits).all { it in allNewShapeTraits }) { lazyMessage } } private fun defaultError() = "test failed" @@ -439,16 +444,16 @@ class ConstraintsMemberShapeTest { lazyMessage: () -> Any = ::defaultError, ) { val memberId = ShapeId.from(member) - check(model.getShape(memberId).isPresent, lazyMessage) + assert(model.getShape(memberId).isPresent) { lazyMessage } val memberShape = model.expectShape(memberId).asMemberShape().get() val memberTargetShape = model.expectShape(memberShape.target) val originalShape = baseModel.expectShape(ShapeId.from(orgModelMember)).asMemberShape().get() // Member shape should not have any constraints on it - check(!memberShape.hasConstraintTrait(), lazyMessage) + assert(!memberShape.hasConstraintTrait()) { lazyMessage } // Target shape has to be same as the original shape - check(memberTargetShape.id == originalShape.target, lazyMessage) + memberTargetShape.id shouldBe originalShape.target } private fun checkShapeHasTrait( @@ -462,13 +467,11 @@ class ConstraintsMemberShapeTest { val memberShape = model.expectShape(memberId).asMemberShape().get() val orgMemberShape = orgModel.expectShape(ShapeId.from(orgModelMember)).asMemberShape().get() - check(memberShape.allTraits.keys.contains(ShapeId.from(traitName))) - { "given $member does not have the $traitName applied to it" } - check(orgMemberShape.allTraits.keys.contains(ShapeId.from(traitName))) - { "given $member does not have the $traitName applied to it in the original model" } + memberShape.allTraits.keys shouldContain ShapeId.from(traitName) + orgMemberShape.allTraits.keys shouldContain ShapeId.from(traitName) val newMemberTrait = memberShape.allTraits[ShapeId.from(traitName)] val oldMemberTrait = orgMemberShape.allTraits[ShapeId.from(traitName)] - check(newMemberTrait == oldMemberTrait) { "contents of the two traits do not match in the transformed model" } + newMemberTrait shouldBe oldMemberTrait } } diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt index a0a9359780..6395870c3f 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt @@ -1,5 +1,6 @@ package software.amazon.smithy.rust.codegen.server.smithy +import io.kotest.matchers.collections.shouldContain import org.junit.jupiter.api.Test import software.amazon.smithy.model.Model import software.amazon.smithy.rust.codegen.core.rustlang.RustModule @@ -97,13 +98,6 @@ class RustCrateInlineModuleComposingWriterTest { } } -// private fun extraRustFun(writer: RustWriter, moduleName: String) { -// writer.rustBlock("pub fn extra()") { -// writer.comment("Module $moduleName") -// writer.rust("""println!("extra function defined inside $moduleName");""") -// } -// } - @Test fun `calling withModule multiple times returns same object on rustModule`() { val testProject = TestWorkspace.testProject(serverTestSymbolProvider(model)) @@ -112,7 +106,7 @@ class RustCrateInlineModuleComposingWriterTest { writers.add(this) } testProject.withModule(ServerRustModule.Model) { - check(writers.contains(this)) + writers shouldContain this } } @@ -164,7 +158,6 @@ class RustCrateInlineModuleComposingWriterTest { modules["g"] = createTestInlineModule(modules["f"]!!, "g") modules["h"] = createTestInlineModule(ServerRustModule.Output, "h") // A different kotlin object but would still go in the right place -// val moduleB = createTestInlineModule(ServerRustModule.Model, "b", "A new module") testProject.withModule(ServerRustModule.Model) { testProject.getInlineModuleWriter().withInlineModule(this, modules["a"]!!) { @@ -185,10 +178,6 @@ class RustCrateInlineModuleComposingWriterTest { testProject.getInlineModuleWriter().withInlineModule(this, modules["b"]!!) { byeWorld(this, "b") } - -// testProject.getInlineModuleWriter().withInlineModule(this, moduleB) { -// extraRustFun(this, "b") -// } } // Write directly to an inline module without specifying the immediate parent. crate::model::b::c @@ -217,7 +206,6 @@ class RustCrateInlineModuleComposingWriterTest { helloWorld(this, "f") } - // It should work even if the inner descendent module was added using `withInlineModuleHierarchy` and then // code is added to the intermediate module using `withInlineModuleHierarchyUsingCrate` testProject.withModule(ServerRustModule.Output) { @@ -250,7 +238,6 @@ class RustCrateInlineModuleComposingWriterTest { this.unitTest("test_b") { rust("crate::model::b::hello_world();") rust("crate::model::b::bye_world();") -// rust("crate::model::b::extra();") } this.unitTest("test_someother_writer_wrote") { rust("crate::model::b::some_other_writer_wrote_this();") diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderDefaultValuesTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderDefaultValuesTest.kt index e64d0c930c..580ebff60c 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderDefaultValuesTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderDefaultValuesTest.kt @@ -33,6 +33,7 @@ import software.amazon.smithy.rust.codegen.core.util.toPascalCase import software.amazon.smithy.rust.codegen.core.util.toSnakeCase import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenConfig import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator +import software.amazon.smithy.rust.codegen.server.smithy.renderInlineMemoryModules import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestRustSettings import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestSymbolProvider @@ -145,6 +146,7 @@ class ServerBuilderDefaultValuesTest { ) } + project.renderInlineMemoryModules() // Run clippy because the builder's code for handling `@default` is prone to upset it. project.compileAndTest(runClippy = true) } diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorTest.kt index 68399eb610..4739906f28 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorTest.kt @@ -9,12 +9,17 @@ import org.junit.jupiter.api.Test import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.implBlock +import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.smithy.generators.StructureGenerator import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest +import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.lookup +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator +import software.amazon.smithy.rust.codegen.server.smithy.initializeInlineModuleWriter +import software.amazon.smithy.rust.codegen.server.smithy.renderInlineMemoryModules import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext class ServerBuilderGeneratorTest { @@ -36,25 +41,38 @@ class ServerBuilderGeneratorTest { """.asSmithyModel() val codegenContext = serverTestCodegenContext(model) - val writer = RustWriter.forModule("model") - val shape = model.lookup("test#Credentials") - - StructureGenerator(model, codegenContext.symbolProvider, writer, shape, emptyList()).render() - val builderGenerator = ServerBuilderGenerator(codegenContext, shape, SmithyValidationExceptionConversionGenerator(codegenContext)) val project = TestWorkspace.testProject() - builderGenerator.render(project, writer) - writer.implBlock(codegenContext.symbolProvider.toSymbol(shape)) { - builderGenerator.renderConvenienceMethod(this) + project.withModule(ServerRustModule.Model) { + val writer = this + val shape = model.lookup("test#Credentials") + + StructureGenerator(model, codegenContext.symbolProvider, writer, shape, emptyList()).render() + val builderGenerator = ServerBuilderGenerator( + codegenContext, + shape, + SmithyValidationExceptionConversionGenerator(codegenContext) + ) + + builderGenerator.render(project, writer) + + writer.implBlock(codegenContext.symbolProvider.toSymbol(shape)) { + builderGenerator.renderConvenienceMethod(this) + } + + project.renderInlineMemoryModules() } - writer.compileAndTest( - """ + + project.unitTest { + rust(""" use super::*; + use crate::model::*; let builder = Credentials::builder() .username(Some("admin".to_owned())) .password(Some("pswd".to_owned())) .secret_key(Some("12345".to_owned())); assert_eq!(format!("{:?}", builder), "Builder { username: Some(\"admin\"), password: \"*** Sensitive Data Redacted ***\", secret_key: \"*** Sensitive Data Redacted ***\" }"); - """, - ) + """) + } + project.compileAndTest() } } diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiatorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiatorTest.kt index d8191ada69..eef80be1c4 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiatorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiatorTest.kt @@ -23,6 +23,7 @@ import software.amazon.smithy.rust.codegen.core.util.dq import software.amazon.smithy.rust.codegen.core.util.lookup import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator +import software.amazon.smithy.rust.codegen.server.smithy.renderInlineMemoryModules import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverRenderWithModelBuilder import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext @@ -181,6 +182,7 @@ class ServerInstantiatorTest { } } } + project.renderInlineMemoryModules() project.compileAndTest() } diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationErrorGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationErrorGeneratorTest.kt index 90b49daa5a..5851344d96 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationErrorGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationErrorGeneratorTest.kt @@ -14,6 +14,7 @@ import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.lookup import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule +import software.amazon.smithy.rust.codegen.server.smithy.renderInlineMemoryModules import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverRenderWithModelBuilder import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestSymbolProvider @@ -94,7 +95,7 @@ class ServerOperationErrorGeneratorTest { let error: GreetingError = variant.into(); """, ) - + project.renderInlineMemoryModules() project.compileAndTest() } } diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt index 8dd45f0f4f..7722851d1c 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt @@ -16,6 +16,7 @@ import software.amazon.smithy.rust.codegen.core.util.lookup import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.createTestInlineModuleCreator +import software.amazon.smithy.rust.codegen.server.smithy.renderInlineMemoryModules import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverRenderWithModelBuilder import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext @@ -130,6 +131,7 @@ class UnconstrainedCollectionGeneratorTest { ) } } + project.renderInlineMemoryModules() project.compileAndTest() } } diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt index 565c693b36..20d6e2e89e 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt @@ -17,6 +17,7 @@ import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule.Model import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.createTestInlineModuleCreator +import software.amazon.smithy.rust.codegen.server.smithy.renderInlineMemoryModules import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverRenderWithModelBuilder import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext @@ -60,7 +61,6 @@ class UnconstrainedMapGeneratorTest { project.withModule(ServerRustModule.ConstrainedModule) { listOf(mapA, mapB).forEach { PubCrateConstrainedMapGenerator(codegenContext, - //this, this.createTestInlineModuleCreator(), it).render() } @@ -169,7 +169,7 @@ class UnconstrainedMapGeneratorTest { ) } } - + project.renderInlineMemoryModules() project.compileAndTest() } } diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt index 9981caab04..774b9110f0 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt @@ -16,6 +16,7 @@ import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.lookup import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.createInlineModuleCreator +import software.amazon.smithy.rust.codegen.server.smithy.renderInlineMemoryModules import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverRenderWithModelBuilder import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext @@ -98,6 +99,7 @@ class UnconstrainedUnionGeneratorTest { ) } } + project.renderInlineMemoryModules() project.compileAndTest() } } diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamBaseRequirements.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamBaseRequirements.kt index f32cedbbbc..8891b8d849 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamBaseRequirements.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamBaseRequirements.kt @@ -102,6 +102,7 @@ abstract class ServerEventStreamBaseRequirements : EventStreamTestRequirements Date: Fri, 17 Feb 2023 15:34:35 +0000 Subject: [PATCH 10/18] ktlintFormat related changes --- .../core/testutil/EventStreamTestTools.kt | 8 +- .../smithy/ConstrainedShapeSymbolProvider.kt | 7 +- .../rust/codegen/server/smithy/Constraints.kt | 19 +- .../RustCrateInlineModuleComposingWriter.kt | 25 +- .../server/smithy/ServerCodegenVisitor.kt | 36 ++- .../server/smithy/ServerSymbolProviders.kt | 2 +- .../smithy/ValidateUnsupportedConstraints.kt | 2 +- .../CollectionConstraintViolationGenerator.kt | 2 - .../generators/ConstrainedBlobGenerator.kt | 3 +- .../generators/ConstrainedNumberGenerator.kt | 1 - .../MapConstraintViolationGenerator.kt | 2 - .../PubCrateConstrainedCollectionGenerator.kt | 2 - .../PubCrateConstrainedMapGenerator.kt | 2 - .../ServerBuilderConstraintViolations.kt | 6 +- .../generators/ServerBuilderGenerator.kt | 4 +- .../UnconstrainedCollectionGenerator.kt | 1 - .../generators/UnconstrainedMapGenerator.kt | 1 - .../generators/UnconstrainedUnionGenerator.kt | 8 +- .../smithy/testutil/ServerTestHelpers.kt | 1 - ...eticStructureFromConstrainedMemberTrait.kt | 9 +- .../ConstrainedMemberTransform.kt | 28 +- .../smithy/ConstraintsMemberShapeTest.kt | 250 +++++++++--------- ...ustCrateInlineModuleComposingWriterTest.kt | 55 ++-- .../ConstrainedBlobGeneratorTest.kt | 2 +- .../ConstrainedCollectionGeneratorTest.kt | 2 +- .../generators/ConstrainedMapGeneratorTest.kt | 2 +- .../ConstrainedNumberGeneratorTest.kt | 2 +- .../ConstrainedStringGeneratorTest.kt | 2 +- .../generators/ServerBuilderGeneratorTest.kt | 24 +- .../UnconstrainedCollectionGeneratorTest.kt | 10 +- .../UnconstrainedMapGeneratorTest.kt | 14 +- .../UnconstrainedUnionGeneratorTest.kt | 2 +- ...verEventStreamUnmarshallerGeneratorTest.kt | 1 - 33 files changed, 279 insertions(+), 256 deletions(-) diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamTestTools.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamTestTools.kt index 8c6e2da440..1529715a7a 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamTestTools.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamTestTools.kt @@ -87,9 +87,9 @@ object EventStreamTestTools { requirements: EventStreamTestRequirements, codegenTarget: CodegenTarget, variety: EventStreamTestVariety, - transformers: List<(Model)->Model> = listOf() - ) : TestWriterDelegator { - val model = (listOf(OperationNormalizer::transform, EventStreamNormalizer::transform) + transformers).fold (testCase.model) { model, transformer -> + transformers: List<(Model) -> Model> = listOf(), + ): TestWriterDelegator { + val model = (listOf(OperationNormalizer::transform, EventStreamNormalizer::transform) + transformers).fold(testCase.model) { model, transformer -> transformer(model) } @@ -137,7 +137,7 @@ object EventStreamTestTools { requirements.renderOperationError(this, model, symbolProvider, operationShape) requirements.renderOperationError(this, model, symbolProvider, unionShape) for (shape in errors) { - requirements.renderError(project,this, codegenContext, shape) + requirements.renderError(project, this, codegenContext, shape) } } val inputOutput = model.lookup("test#TestStreamInputOutput") diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt index cfc55fc3e0..e061894f75 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt @@ -64,7 +64,7 @@ class ConstrainedShapeSymbolProvider( private val base: RustSymbolProvider, private val model: Model, private val serviceShape: ServiceShape, - private val publicConstrainedTypes: Boolean + private val publicConstrainedTypes: Boolean, ) : WrappingSymbolProvider(base) { private val nullableIndex = NullableIndex.of(model) @@ -150,7 +150,6 @@ class ConstrainedShapeSymbolProvider( .isEmpty() } - /** * Returns the pair (Rust Symbol Name, Inline Module) for the shape. At the time of model transformation all * constrained member shapes are extracted and are given a model-wide unique name. However, the generated code @@ -171,8 +170,8 @@ class ConstrainedShapeSymbolProvider( val renameTo = syntheticMemberTrait.member.memberName ?: syntheticMemberTrait.member.id.name Pair(renameTo.toPascalCase(), builderModule) } else { - // For List, Union and Map, the new shape defined for a constrained member shape - // need to be placed into an inline module named `pub {container_name_in_snake_case}` + // For non-structure shapes, the new shape defined for a constrained member shape + // needs to be placed in an inline module named `pub {container_name_in_snake_case}`. val moduleName = RustReservedWords.escapeIfNeeded(syntheticMemberTrait.container.id.name.toSnakeCase()) val innerModuleName = moduleName + if (pubCrateServerBuilder) { "_internal" diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt index d6a1f88eb6..9edc7de291 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt @@ -14,7 +14,6 @@ import software.amazon.smithy.model.shapes.IntegerShape import software.amazon.smithy.model.shapes.LongShape import software.amazon.smithy.model.shapes.MapShape import software.amazon.smithy.model.shapes.MemberShape -import software.amazon.smithy.model.shapes.ServiceShape import software.amazon.smithy.model.shapes.Shape import software.amazon.smithy.model.shapes.ShortShape import software.amazon.smithy.model.shapes.SimpleShape @@ -170,7 +169,6 @@ fun Shape.typeNameContainsNonPublicType( else -> UNREACHABLE("the above arms should be exhaustive, but we received shape: $this") } - /** * For synthetic shapes that are added to the model because of member constrained shapes, it returns * the "container" and "the member shape" that originally had the constraint trait. For all other @@ -181,7 +179,6 @@ fun Shape.overriddenConstrainedMemberInfo(): Pair? { return Pair(trait.container, trait.member) } - /** * Returns the parent and the inline module that this particular shape should go in. */ @@ -191,8 +188,7 @@ fun Shape.getParentAndInlineModuleForConstrainedMember(symbolProvider: SymbolPro val structureModule = symbolProvider.toSymbol(overriddenTrait.container).module() val builderModule = overriddenTrait.container.serverBuilderModule(symbolProvider, pubCrateServerBuilder) Pair(structureModule, builderModule) - } - else { + } else { // For constrained member shapes, the ConstraintViolation code needs to go in an inline rust module // that is a descendant of the module that contains the extracted shape itself. return if (!pubCrateServerBuilder) { @@ -203,15 +199,14 @@ fun Shape.getParentAndInlineModuleForConstrainedMember(symbolProvider: SymbolPro "Parent module of $id should not be an inline module" } Pair(shapeModule.parent as RustModule.LeafModule, shapeModule) - } - else { + } else { val name = RustReservedWords.escapeIfNeeded(overriddenTrait.container.id.name).toSnakeCase() + "_internal" val innerModule = RustModule.new( - name = name, - visibility = Visibility.PUBCRATE, - parent = ServerRustModule.Model, - inline = true, - ) + name = name, + visibility = Visibility.PUBCRATE, + parent = ServerRustModule.Model, + inline = true, + ) Pair(ServerRustModule.Model, innerModule) } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt index 6e8fefa0c1..ca4c575e91 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt @@ -1,3 +1,8 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + package software.amazon.smithy.rust.codegen.server.smithy import software.amazon.smithy.codegen.core.Symbol @@ -15,14 +20,14 @@ typealias InlineModuleCreator = (Symbol, Writable) -> Unit /** * Initializes RustCrate -> InnerModule data structure. */ -fun RustCrate.initializeInlineModuleWriter(debugMode : Boolean): InnerModule = +fun RustCrate.initializeInlineModuleWriter(debugMode: Boolean): InnerModule = crateToInlineModule .getOrPut(this) { InnerModule(debugMode) } /** * Returns the InnerModule for the given RustCrate */ -fun RustCrate.getInlineModuleWriter() : InnerModule { +fun RustCrate.getInlineModuleWriter(): InnerModule { return crateToInlineModule.getOrPut(this) { InnerModule(false) } } @@ -94,7 +99,6 @@ fun RustCrate.useShapeWriterOrUseWithStructureBuilder( } } - fun RustCrate.renderInlineMemoryModules() { val inlineModule = crateToInlineModule[this] check(inlineModule != null) { @@ -102,6 +106,7 @@ fun RustCrate.renderInlineMemoryModules() { } inlineModule.render() } + /** * Given a `RustWriter` calls the `Writable` using a `RustWriter` for the `inlineModule` */ @@ -130,7 +135,7 @@ fun RustWriter.createTestInlineModuleCreator(): InlineModuleCreator { /** * Maintains the `RustWriter` that has been created for a `RustModule.LeafModule`. */ -private data class InlineModuleWithWriter(val inlineModule : RustModule.LeafModule, val writer : RustWriter) +private data class InlineModuleWithWriter(val inlineModule: RustModule.LeafModule, val writer: RustWriter) /** * For each RustCrate a separate mapping of inline-module to `RustWriter` is maintained. @@ -138,7 +143,7 @@ private data class InlineModuleWithWriter(val inlineModule : RustModule.LeafModu private val crateToInlineModule: ConcurrentHashMap = ConcurrentHashMap() -class InnerModule(debugMode : Boolean) { +class InnerModule(debugMode: Boolean) { private val topLevelModuleWriters: MutableSet = mutableSetOf() private val inlineModuleWriters: ConcurrentHashMap> = ConcurrentHashMap() private val docWriters: ConcurrentHashMap> = ConcurrentHashMap() @@ -230,7 +235,6 @@ class InnerModule(debugMode : Boolean) { return writer } - /** * Returns the complete hierarchy of a `RustModule.LeafModule` from top to bottom */ @@ -246,12 +250,11 @@ class InnerModule(debugMode : Boolean) { return hierarchy } - /** * Writes out each inline module's code (`toString`) to the respective top level `RustWriter`. */ fun render() { - var writerToAddDependencies : RustWriter? = null + var writerToAddDependencies: RustWriter? = null fun writeInlineCode(rustWriter: RustWriter, code: String) { val inlineCode = code.drop(emptyLineCount) @@ -303,7 +306,7 @@ class InnerModule(debugMode : Boolean) { /** * Records the root of a dependency graph of inline modules. */ - private fun registerTopMostWriter(outerWriter: RustWriter) : MutableList { + private fun registerTopMostWriter(outerWriter: RustWriter): MutableList { topLevelModuleWriters.add(outerWriter) return inlineModuleWriters.getOrPut(outerWriter) { mutableListOf() } } @@ -314,7 +317,7 @@ class InnerModule(debugMode : Boolean) { */ private fun findOrAddToList( inlineModuleList: MutableList, - lookForModule: RustModule.LeafModule + lookForModule: RustModule.LeafModule, ): RustWriter { val inlineModuleAndWriter = inlineModuleList.firstOrNull() { it.inlineModule.name == lookForModule.name @@ -333,7 +336,7 @@ class InnerModule(debugMode : Boolean) { } private fun writeDocs(innerModule: RustModule.LeafModule) { - docWriters[innerModule]?.forEach{ + docWriters[innerModule]?.forEach { it() } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt index bcaaa33cd3..a686c6ad04 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt @@ -78,8 +78,8 @@ import software.amazon.smithy.rust.codegen.server.smithy.generators.protocol.Ser import software.amazon.smithy.rust.codegen.server.smithy.protocols.ServerProtocolLoader import software.amazon.smithy.rust.codegen.server.smithy.traits.isReachableFromOperationInput import software.amazon.smithy.rust.codegen.server.smithy.transformers.AttachValidationExceptionToConstrainedOperationInputsInAllowList -import software.amazon.smithy.rust.codegen.server.smithy.transformers.RecursiveConstraintViolationBoxer import software.amazon.smithy.rust.codegen.server.smithy.transformers.ConstrainedMemberTransform +import software.amazon.smithy.rust.codegen.server.smithy.transformers.RecursiveConstraintViolationBoxer import software.amazon.smithy.rust.codegen.server.smithy.transformers.RemoveEbsModelValidationException import software.amazon.smithy.rust.codegen.server.smithy.transformers.ShapesReachableFromOperationInputTagger import java.util.logging.Logger @@ -350,9 +350,11 @@ open class ServerCodegenVisitor( if (!isDirectlyConstrained) { logger.info("[rust-server-codegen] Generating a constrained type for collection shape $shape") rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.ConstrainedModule, shape, codegenContext) { - PubCrateConstrainedCollectionGenerator(codegenContext, + PubCrateConstrainedCollectionGenerator( + codegenContext, rustCrate.createInlineModuleCreator(), - shape).render() + shape, + ).render() } } } @@ -375,8 +377,7 @@ open class ServerCodegenVisitor( CollectionConstraintViolationGenerator( codegenContext, rustCrate.createInlineModuleCreator(), - shape, - constraintsInfo, + shape, constraintsInfo, validationExceptionConversionGenerator, ).render() } @@ -394,17 +395,21 @@ open class ServerCodegenVisitor( if (renderUnconstrainedMap) { logger.info("[rust-server-codegen] Generating an unconstrained type for map $shape") rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.UnconstrainedModule, shape, codegenContext) { - UnconstrainedMapGenerator(codegenContext, + UnconstrainedMapGenerator( + codegenContext, rustCrate.createInlineModuleCreator(), - shape).render() + shape, + ).render() } if (!isDirectlyConstrained) { logger.info("[rust-server-codegen] Generating a constrained type for map $shape") rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.ConstrainedModule, shape, codegenContext) { - PubCrateConstrainedMapGenerator(codegenContext, + PubCrateConstrainedMapGenerator( + codegenContext, rustCrate.createInlineModuleCreator(), - shape).render() + shape, + ).render() } } } @@ -451,8 +456,8 @@ open class ServerCodegenVisitor( if (shape.isDirectlyConstrained(codegenContext.symbolProvider)) { logger.info("[rust-server-codegen] Generating a constrained integral $shape") rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.Model, shape, codegenContext) { - ConstrainedNumberGenerator(codegenContext, - rustCrate.createInlineModuleCreator(), + ConstrainedNumberGenerator( + codegenContext, rustCrate.createInlineModuleCreator(), this, shape, validationExceptionConversionGenerator, @@ -485,11 +490,13 @@ open class ServerCodegenVisitor( } else if (!shape.hasTrait() && shape.isDirectlyConstrained(codegenContext.symbolProvider)) { logger.info("[rust-server-codegen] Generating a constrained string $shape") rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.Model, shape, codegenContext) { - ConstrainedStringGenerator(codegenContext, + ConstrainedStringGenerator( + codegenContext, rustCrate.createInlineModuleCreator(), this, shape, - validationExceptionConversionGenerator).render() + validationExceptionConversionGenerator, + ).render() } } } @@ -568,7 +575,8 @@ open class ServerCodegenVisitor( if (shape.isDirectlyConstrained(codegenContext.symbolProvider)) { rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.Model, shape, codegenContext) { - ConstrainedBlobGenerator(codegenContext, + ConstrainedBlobGenerator( + codegenContext, rustCrate.createInlineModuleCreator(), this, shape, diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerSymbolProviders.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerSymbolProviders.kt index 98ab7364a3..0c6bec0c6f 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerSymbolProviders.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerSymbolProviders.kt @@ -38,7 +38,7 @@ class ServerSymbolProviders private constructor( service, symbolVisitorConfig, publicConstrainedTypes, - true + true, ), unconstrainedShapeSymbolProvider = UnconstrainedShapeSymbolProvider( baseSymbolProviderFactory( diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraints.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraints.kt index fb85601fa7..73a59eca96 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraints.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraints.kt @@ -236,7 +236,7 @@ fun validateUnsupportedConstraints( .toSet() val messages = - unsupportedLengthTraitOnStreamingBlobShapeSet.map { it.intoLogMessage(codegenConfig.ignoreUnsupportedConstraints) } + + unsupportedLengthTraitOnStreamingBlobShapeSet.map { it.intoLogMessage(codegenConfig.ignoreUnsupportedConstraints) } + unsupportedConstraintShapeReachableViaAnEventStreamSet.map { it.intoLogMessage(codegenConfig.ignoreUnsupportedConstraints) } + unsupportedRangeTraitOnShapeSet.map { it.intoLogMessage(codegenConfig.ignoreUnsupportedConstraints) } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/CollectionConstraintViolationGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/CollectionConstraintViolationGenerator.kt index 930165648c..e2a177f536 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/CollectionConstraintViolationGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/CollectionConstraintViolationGenerator.kt @@ -6,12 +6,10 @@ package software.amazon.smithy.rust.codegen.server.smithy.generators import software.amazon.smithy.model.shapes.CollectionShape -import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.Visibility import software.amazon.smithy.rust.codegen.core.rustlang.join import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.smithy.makeRustBoxed -import software.amazon.smithy.rust.codegen.core.smithy.module import software.amazon.smithy.rust.codegen.core.util.hasTrait import software.amazon.smithy.rust.codegen.core.util.letIf import software.amazon.smithy.rust.codegen.server.smithy.InlineModuleCreator diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGenerator.kt index 76770b52d2..5a1c3bc4e1 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGenerator.kt @@ -21,7 +21,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.expectRustMetadata import software.amazon.smithy.rust.codegen.core.smithy.makeMaybeConstrained -import software.amazon.smithy.rust.codegen.core.smithy.module import software.amazon.smithy.rust.codegen.core.smithy.rustType import software.amazon.smithy.rust.codegen.core.util.orNull import software.amazon.smithy.rust.codegen.server.smithy.InlineModuleCreator @@ -32,7 +31,7 @@ import software.amazon.smithy.rust.codegen.server.smithy.validationErrorMessage class ConstrainedBlobGenerator( val codegenContext: ServerCodegenContext, - private val inlineModuleCreator : InlineModuleCreator, + private val inlineModuleCreator: InlineModuleCreator, val writer: RustWriter, val shape: BlobShape, private val validationExceptionConversionGenerator: ValidationExceptionConversionGenerator, diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGenerator.kt index 61e7aed6a5..45ef7dd0a1 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGenerator.kt @@ -25,7 +25,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.expectRustMetadata import software.amazon.smithy.rust.codegen.core.smithy.makeMaybeConstrained -import software.amazon.smithy.rust.codegen.core.smithy.module import software.amazon.smithy.rust.codegen.core.util.UNREACHABLE import software.amazon.smithy.rust.codegen.core.util.expectTrait import software.amazon.smithy.rust.codegen.core.util.redactIfNecessary diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/MapConstraintViolationGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/MapConstraintViolationGenerator.kt index c65e6c38ca..065a4067c7 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/MapConstraintViolationGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/MapConstraintViolationGenerator.kt @@ -8,11 +8,9 @@ package software.amazon.smithy.rust.codegen.server.smithy.generators import software.amazon.smithy.model.shapes.MapShape import software.amazon.smithy.model.shapes.StringShape import software.amazon.smithy.model.traits.LengthTrait -import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.Visibility import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.smithy.makeRustBoxed -import software.amazon.smithy.rust.codegen.core.smithy.module import software.amazon.smithy.rust.codegen.core.util.hasTrait import software.amazon.smithy.rust.codegen.core.util.letIf import software.amazon.smithy.rust.codegen.server.smithy.InlineModuleCreator diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/PubCrateConstrainedCollectionGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/PubCrateConstrainedCollectionGenerator.kt index 647c99273b..ac4426fa29 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/PubCrateConstrainedCollectionGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/PubCrateConstrainedCollectionGenerator.kt @@ -7,7 +7,6 @@ package software.amazon.smithy.rust.codegen.server.smithy.generators import software.amazon.smithy.model.shapes.CollectionShape import software.amazon.smithy.model.shapes.MapShape -import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.conditionalBlock import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock @@ -16,7 +15,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.withBlock import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.isOptional -import software.amazon.smithy.rust.codegen.core.smithy.module import software.amazon.smithy.rust.codegen.server.smithy.InlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.canReachConstrainedShape diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/PubCrateConstrainedMapGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/PubCrateConstrainedMapGenerator.kt index 9e8308dc8b..838d4da085 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/PubCrateConstrainedMapGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/PubCrateConstrainedMapGenerator.kt @@ -8,7 +8,6 @@ package software.amazon.smithy.rust.codegen.server.smithy.generators import software.amazon.smithy.model.shapes.CollectionShape import software.amazon.smithy.model.shapes.MapShape import software.amazon.smithy.model.shapes.StringShape -import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.conditionalBlock import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock @@ -17,7 +16,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.withBlock import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.isOptional -import software.amazon.smithy.rust.codegen.core.smithy.module import software.amazon.smithy.rust.codegen.server.smithy.InlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.canReachConstrainedShape diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderConstraintViolations.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderConstraintViolations.kt index 50659f0d9e..799997c819 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderConstraintViolations.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderConstraintViolations.kt @@ -71,9 +71,11 @@ class ServerBuilderConstraintViolations( writer.docs("Holds one variant for each of the ways the builder can fail.") if (nonExhaustive) Attribute.NonExhaustive.render(writer) val constraintViolationSymbolName = constraintViolationSymbolProvider.toSymbol(shape).name - writer.rustBlock(""" + writer.rustBlock( + """ ##[allow(clippy::enum_variant_names)] - pub${if (visibility == Visibility.PUBCRATE) " (crate) " else ""} enum $constraintViolationSymbolName""") { + pub${if (visibility == Visibility.PUBCRATE) " (crate) " else ""} enum $constraintViolationSymbolName""", + ) { renderConstraintViolations(writer) } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGenerator.kt index 8b1d8c944a..34a7115714 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGenerator.kt @@ -155,8 +155,8 @@ class ServerBuilderGenerator( "MaybeConstrained" to RuntimeType.MaybeConstrained, ) - fun render(rustCrate : RustCrate, writer: RustWriter) { - val docWriter : () -> Unit = { writer.docs("See #D.", structureSymbol) } + fun render(rustCrate: RustCrate, writer: RustWriter) { + val docWriter: () -> Unit = { writer.docs("See #D.", structureSymbol) } rustCrate.withInMemoryInlineModule(writer, builderSymbol.module(), docWriter) { renderBuilder(this) } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGenerator.kt index eb5c06b561..6916617b6f 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGenerator.kt @@ -18,7 +18,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.isOptional import software.amazon.smithy.rust.codegen.core.smithy.makeMaybeConstrained -import software.amazon.smithy.rust.codegen.core.smithy.module import software.amazon.smithy.rust.codegen.core.util.hasTrait import software.amazon.smithy.rust.codegen.server.smithy.InlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.PubCrateConstraintViolationSymbolProvider diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGenerator.kt index 9f1c2c6d39..0862a26987 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGenerator.kt @@ -19,7 +19,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.isOptional import software.amazon.smithy.rust.codegen.core.smithy.makeMaybeConstrained -import software.amazon.smithy.rust.codegen.core.smithy.module import software.amazon.smithy.rust.codegen.core.util.hasTrait import software.amazon.smithy.rust.codegen.server.smithy.InlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.PubCrateConstraintViolationSymbolProvider diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGenerator.kt index a6d14653e6..f3ec8322c7 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGenerator.kt @@ -135,12 +135,14 @@ class UnconstrainedUnionGenerator( } inlineModuleCreator( - constraintViolationSymbol + constraintViolationSymbol, ) { Attribute(derive(RuntimeType.Debug, RuntimeType.PartialEq)).render(this) - rustBlock(""" + rustBlock( + """ ##[allow(clippy::enum_variant_names)] - pub${if (constraintViolationVisibility == Visibility.PUBCRATE) " (crate)" else ""} enum $constraintViolationName""") { + pub${if (constraintViolationVisibility == Visibility.PUBCRATE) " (crate)" else ""} enum $constraintViolationName""", + ) { constraintViolations().forEach { renderConstraintViolation(this, it) } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt index 452d7860c9..421e85902b 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt @@ -27,7 +27,6 @@ import software.amazon.smithy.rust.codegen.server.smithy.ServerRustSettings import software.amazon.smithy.rust.codegen.server.smithy.ServerSymbolProviders import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.generators.ServerBuilderGenerator -import software.amazon.smithy.rust.codegen.server.smithy.getInlineModuleWriter // These are the settings we default to if the user does not override them in their `smithy-build.json`. val ServerTestSymbolVisitorConfig = SymbolVisitorConfig( diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/traits/SyntheticStructureFromConstrainedMemberTrait.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/traits/SyntheticStructureFromConstrainedMemberTrait.kt index 0bc2010b75..de5890c87a 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/traits/SyntheticStructureFromConstrainedMemberTrait.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/traits/SyntheticStructureFromConstrainedMemberTrait.kt @@ -1,3 +1,8 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + package software.amazon.smithy.rust.codegen.server.smithy.traits import software.amazon.smithy.model.node.Node @@ -9,8 +14,8 @@ import software.amazon.smithy.model.traits.AnnotationTrait /** * Trait applied to an overridden shape indicating the member of this new shape type */ -class SyntheticStructureFromConstrainedMemberTrait(val container : Shape, val member: MemberShape): AnnotationTrait(SyntheticStructureFromConstrainedMemberTrait.ID, Node.objectNode()) { +class SyntheticStructureFromConstrainedMemberTrait(val container: Shape, val member: MemberShape) : AnnotationTrait(SyntheticStructureFromConstrainedMemberTrait.ID, Node.objectNode()) { companion object { - val ID : ShapeId = ShapeId.from("smithy.api.internal#overriddenMember") + val ID: ShapeId = ShapeId.from("smithy.api.internal#overriddenMember") } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/transformers/ConstrainedMemberTransform.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/transformers/ConstrainedMemberTransform.kt index 04963ab5a0..3ab99ce64d 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/transformers/ConstrainedMemberTransform.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/transformers/ConstrainedMemberTransform.kt @@ -1,3 +1,8 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + package software.amazon.smithy.rust.codegen.server.smithy.transformers import software.amazon.smithy.model.Model @@ -15,14 +20,13 @@ import software.amazon.smithy.model.transform.ModelTransformer import software.amazon.smithy.rust.codegen.core.smithy.DirectedWalker import software.amazon.smithy.rust.codegen.core.smithy.traits.SyntheticInputTrait import software.amazon.smithy.rust.codegen.core.smithy.traits.SyntheticOutputTrait +import software.amazon.smithy.rust.codegen.core.util.UNREACHABLE +import software.amazon.smithy.rust.codegen.core.util.orNull +import software.amazon.smithy.rust.codegen.server.smithy.allConstraintTraits import software.amazon.smithy.rust.codegen.server.smithy.traits.SyntheticStructureFromConstrainedMemberTrait import software.amazon.smithy.utils.ToSmithyBuilder import java.lang.IllegalStateException import java.util.* -import software.amazon.smithy.rust.codegen.core.util.UNREACHABLE -import software.amazon.smithy.rust.codegen.core.util.orNull -import software.amazon.smithy.rust.codegen.core.util.orNullIfEmpty -import software.amazon.smithy.rust.codegen.server.smithy.allConstraintTraits /** * Transforms all member shapes that have constraints on them into equivalent non-constrained @@ -78,12 +82,12 @@ object ConstrainedMemberTransform { // The transformer will add new shapes, and will replace existing member shapes' target // with the newly added shapes. val transformations = model.operationShapes - .flatMap { listOfNotNull(it.input.orNull(), it.output.orNull()) + it.errors } + .flatMap { listOfNotNull(it.input.orNull(), it.output.orNull()) + it.errors } .mapNotNull { model.expectShape(it).asStructureShape().orElse(null) } - .filter { it.hasTrait(SyntheticInputTrait.ID) || it.hasTrait(SyntheticOutputTrait.ID) } - .flatMap { walker.walkShapes(it) } - .filter { it is StructureShape || it is ListShape || it is UnionShape || it is MapShape } - .flatMap { it.constrainedMembers() } + .filter { it.hasTrait(SyntheticInputTrait.ID) || it.hasTrait(SyntheticOutputTrait.ID) } + .flatMap { walker.walkShapes(it) } + .filter { it is StructureShape || it is ListShape || it is UnionShape || it is MapShape } + .flatMap { it.constrainedMembers() } .mapNotNull { val transformation = it.makeNonConstrained(model, additionalNames) // Keep record of new names that have been generated to ensure none of them regenerated. @@ -150,8 +154,9 @@ object ConstrainedMemberTransform { // by appending a new number as the suffix. (0..100).forEach { val extractedStructName = if (it == 0) makeStructName("") else makeStructName("$it") - if (structNameIsUnique(extractedStructName)) + if (structNameIsUnique(extractedStructName)) { return extractedStructName + } } throw IllegalStateException("A unique name for the overridden structure type could not be generated") @@ -181,8 +186,9 @@ object ConstrainedMemberTransform { // have all of the original constraints that have not been overridden, and the ones // that this member shape overrides. val targetShape = model.expectShape(this.target) - if (targetShape !is ToSmithyBuilder<*>) + if (targetShape !is ToSmithyBuilder<*>) { UNREACHABLE("Member target shapes will always be buildable") + } return when (val builder = targetShape.toBuilder()) { is AbstractShapeBuilder<*, *> -> { diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt index f10b5d7473..24249fa25e 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt @@ -1,3 +1,8 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + package software.amazon.smithy.rust.codegen.server.smithy import io.kotest.matchers.collections.shouldContain @@ -10,12 +15,11 @@ import software.amazon.smithy.model.traits.RequiredTrait 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.testutil.asSmithyModel -import software.amazon.smithy.rust.codegen.server.smithy.transformers.ConstrainedMemberTransform import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig import software.amazon.smithy.rust.codegen.core.smithy.RuntimeCrateLocation import software.amazon.smithy.rust.codegen.core.smithy.RustCrate import software.amazon.smithy.rust.codegen.core.smithy.transformers.OperationNormalizer +import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.generatePluginContext import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.runCommand @@ -26,132 +30,133 @@ import software.amazon.smithy.rust.codegen.server.smithy.customizations.ServerRe import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionDecorator import software.amazon.smithy.rust.codegen.server.smithy.customize.CombinedServerCodegenDecorator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext +import software.amazon.smithy.rust.codegen.server.smithy.transformers.ConstrainedMemberTransform import java.io.File import java.nio.file.Path class ConstraintsMemberShapeTest { private val outputModelOnly = """ - namespace constrainedMemberShape + namespace constrainedMemberShape - use aws.protocols#restJson1 - use aws.api#data + use aws.protocols#restJson1 + use aws.api#data - @restJson1 - service ConstrainedService { - operations: [OperationUsingGet] - } + @restJson1 + service ConstrainedService { + operations: [OperationUsingGet] + } - @http(uri: "/anOperation", method: "GET") - operation OperationUsingGet { - output : OperationUsingGetOutput - } - structure OperationUsingGetOutput { - plainLong : Long - plainInteger : Integer - plainShort : Short - plainByte : Byte - plainFloat: Float - plainString: String - - @range(min: 1, max:100) - constrainedLong : Long - @range(min: 2, max:100) - constrainedInteger : Integer - @range(min: 3, max:100) - constrainedShort : Short - @range(min: 4, max:100) - constrainedByte : Byte - @length(max: 100) - constrainedString: String - - @required - @range(min: 5, max:100) - requiredConstrainedLong : Long - @required - @range(min: 6, max:100) - requiredConstrainedInteger : Integer - @required - @range(min: 7, max:100) - requiredConstrainedShort : Short - @required - @range(min: 8, max:100) - requiredConstrainedByte : Byte - @required - @length(max: 101) - requiredConstrainedString: String - - patternString : PatternString - - @data("content") - @pattern("^[g-m]+${'$'}") - constrainedPatternString : PatternString - - plainStringList : PlainStringList - patternStringList : PatternStringList - patternStringListOverride : PatternStringListOverride - - plainStructField : PlainStructWithInteger - structWithConstrainedMember : StructWithConstrainedMember - structWithConstrainedMemberOverride : StructWithConstrainedMemberOverride - - patternUnion: PatternUnion - patternUnionOverride: PatternUnionOverride - patternMap : PatternMap - patternMapOverride: PatternMapOverride - } - list ListWithIntegerMemberStruct { - member: PlainStructWithInteger - } - structure PlainStructWithInteger { - lat : Integer - long : Integer - } - structure StructWithConstrainedMember { - @range(min: 100) - lat : Integer - long : Integer - } - structure StructWithConstrainedMemberOverride { - @range(min: 10) - lat : RangedInteger - @range(min: 10, max:100) - long : RangedInteger - } - list PlainStringList { - member: String - } - list PatternStringList { - member: PatternString - } - list PatternStringListOverride { - @pattern("^[g-m]+${'$'}") - member: PatternString - } - map PatternMap { - key: PatternString, - value: PatternString - } - map PatternMapOverride { - @pattern("^[g-m]+${'$'}") - key: PatternString, - @pattern("^[g-m]+${'$'}") - value: PatternString - } - union PatternUnion { - first: PatternString, - second: PatternString - } - union PatternUnionOverride { - @pattern("^[g-m]+${'$'}") - first: PatternString, - @pattern("^[g-m]+${'$'}") - second: PatternString - } - @pattern("^[a-m]+${'$'}") - string PatternString - @range(min: 0, max:1000) - integer RangedInteger - """.asSmithyModel() + @http(uri: "/anOperation", method: "GET") + operation OperationUsingGet { + output : OperationUsingGetOutput + } + structure OperationUsingGetOutput { + plainLong : Long + plainInteger : Integer + plainShort : Short + plainByte : Byte + plainFloat: Float + plainString: String + + @range(min: 1, max:100) + constrainedLong : Long + @range(min: 2, max:100) + constrainedInteger : Integer + @range(min: 3, max:100) + constrainedShort : Short + @range(min: 4, max:100) + constrainedByte : Byte + @length(max: 100) + constrainedString: String + + @required + @range(min: 5, max:100) + requiredConstrainedLong : Long + @required + @range(min: 6, max:100) + requiredConstrainedInteger : Integer + @required + @range(min: 7, max:100) + requiredConstrainedShort : Short + @required + @range(min: 8, max:100) + requiredConstrainedByte : Byte + @required + @length(max: 101) + requiredConstrainedString: String + + patternString : PatternString + + @data("content") + @pattern("^[g-m]+${'$'}") + constrainedPatternString : PatternString + + plainStringList : PlainStringList + patternStringList : PatternStringList + patternStringListOverride : PatternStringListOverride + + plainStructField : PlainStructWithInteger + structWithConstrainedMember : StructWithConstrainedMember + structWithConstrainedMemberOverride : StructWithConstrainedMemberOverride + + patternUnion: PatternUnion + patternUnionOverride: PatternUnionOverride + patternMap : PatternMap + patternMapOverride: PatternMapOverride + } + list ListWithIntegerMemberStruct { + member: PlainStructWithInteger + } + structure PlainStructWithInteger { + lat : Integer + long : Integer + } + structure StructWithConstrainedMember { + @range(min: 100) + lat : Integer + long : Integer + } + structure StructWithConstrainedMemberOverride { + @range(min: 10) + lat : RangedInteger + @range(min: 10, max:100) + long : RangedInteger + } + list PlainStringList { + member: String + } + list PatternStringList { + member: PatternString + } + list PatternStringListOverride { + @pattern("^[g-m]+${'$'}") + member: PatternString + } + map PatternMap { + key: PatternString, + value: PatternString + } + map PatternMapOverride { + @pattern("^[g-m]+${'$'}") + key: PatternString, + @pattern("^[g-m]+${'$'}") + value: PatternString + } + union PatternUnion { + first: PatternString, + second: PatternString + } + union PatternUnionOverride { + @pattern("^[g-m]+${'$'}") + first: PatternString, + @pattern("^[g-m]+${'$'}") + second: PatternString + } + @pattern("^[a-m]+${'$'}") + string PatternString + @range(min: 0, max:1000) + integer RangedInteger + """.asSmithyModel() private fun loadModel(model: Model): Model = ConstrainedMemberTransform.transform(OperationNormalizer.transform(model)) @@ -314,7 +319,7 @@ class ConstraintsMemberShapeTest { "builder_module_has_${typeName.toSnakeCase()}", """ #[allow(unused_imports)] use crate::output::operation_using_get_output::$typeName; - """, + """, ) } @@ -420,7 +425,8 @@ class ConstraintsMemberShapeTest { assert( leftOutConstraintTrait.isEmpty() || leftOutConstraintTrait.all { it.toShapeId() == RequiredTrait.ID - },) { lazyMessage } + }, + ) { lazyMessage } // In case the target shape has some more constraints, which the member shape did not override, // then those still need to apply on the new standalone shape that has been defined. diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt index 6395870c3f..2fbebee1cf 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt @@ -1,3 +1,8 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + package software.amazon.smithy.rust.codegen.server.smithy import io.kotest.matchers.collections.shouldContain @@ -25,33 +30,33 @@ class RustCrateInlineModuleComposingWriterTest { private val rustCrate: RustCrate private val codegenContext: ServerCodegenContext private val model: Model = """ - ${'$'}version: "2.0" - namespace test + ${'$'}version: "2.0" + namespace test - use aws.api#data - use aws.protocols#restJson1 + use aws.api#data + use aws.protocols#restJson1 - @title("Weather Service") - @restJson1 - service WeatherService { - operations: [MalformedPatternOverride] - } + @title("Weather Service") + @restJson1 + service WeatherService { + operations: [MalformedPatternOverride] + } - @suppress(["UnstableTrait"]) - @http(uri: "/MalformedPatternOverride", method: "GET") - operation MalformedPatternOverride { - output: MalformedPatternOverrideInput, - errors: [] - } + @suppress(["UnstableTrait"]) + @http(uri: "/MalformedPatternOverride", method: "GET") + operation MalformedPatternOverride { + output: MalformedPatternOverrideInput, + errors: [] + } - structure MalformedPatternOverrideInput { - @pattern("^[g-m]+${'$'}") - string: PatternString, - } + structure MalformedPatternOverrideInput { + @pattern("^[g-m]+${'$'}") + string: PatternString, + } - @pattern("^[a-m]+${'$'}") - string PatternString - """.trimIndent().asSmithyModel() + @pattern("^[a-m]+${'$'}") + string PatternString + """.trimIndent().asSmithyModel() init { codegenContext = serverTestCodegenContext(model) @@ -66,7 +71,7 @@ class RustCrateInlineModuleComposingWriterTest { rustCrate = RustCrate(context.fileManifest, codegenContext.symbolProvider, settings.codegenConfig) } - private fun createTestInlineModule(parentModule: RustModule, moduleName : String, documentation : String? = null) : RustModule.LeafModule = + private fun createTestInlineModule(parentModule: RustModule, moduleName: String, documentation: String? = null): RustModule.LeafModule = RustModule.new( moduleName, visibility = Visibility.PUBLIC, @@ -75,7 +80,7 @@ class RustCrateInlineModuleComposingWriterTest { inline = true, ) - private fun createTestOrphanInlineModule(moduleName : String) : RustModule.LeafModule = + private fun createTestOrphanInlineModule(moduleName: String): RustModule.LeafModule = RustModule.new( moduleName, visibility = Visibility.PUBLIC, @@ -101,7 +106,7 @@ class RustCrateInlineModuleComposingWriterTest { @Test fun `calling withModule multiple times returns same object on rustModule`() { val testProject = TestWorkspace.testProject(serverTestSymbolProvider(model)) - val writers : MutableSet = mutableSetOf() + val writers: MutableSet = mutableSetOf() testProject.withModule(ServerRustModule.Model) { writers.add(this) } diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt index 4a09e4d927..060e0166a4 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt @@ -23,8 +23,8 @@ import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.dq import software.amazon.smithy.rust.codegen.core.util.lookup import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule -import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.createTestInlineModuleCreator +import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext import java.util.stream.Stream diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt index 90702c81af..cce7da4aa6 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt @@ -33,8 +33,8 @@ import software.amazon.smithy.rust.codegen.core.util.UNREACHABLE import software.amazon.smithy.rust.codegen.core.util.lookup import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule -import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.createTestInlineModuleCreator +import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.transformers.ShapesReachableFromOperationInputTagger import java.util.stream.Stream diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt index 87b87600a3..0eebb7e36b 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt @@ -24,8 +24,8 @@ import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.lookup import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule -import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.createTestInlineModuleCreator +import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.transformers.ShapesReachableFromOperationInputTagger import java.util.stream.Stream diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt index 1be89ff62d..5a78574c93 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt @@ -20,8 +20,8 @@ import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.lookup import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule -import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.createTestInlineModuleCreator +import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext import java.util.stream.Stream diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt index 987d402b6b..62a7d061c3 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt @@ -23,8 +23,8 @@ import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.CommandFailed import software.amazon.smithy.rust.codegen.core.util.lookup import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule -import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.createTestInlineModuleCreator +import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext import java.util.stream.Stream diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorTest.kt index 4739906f28..d26e6b35db 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGeneratorTest.kt @@ -7,7 +7,6 @@ package software.amazon.smithy.rust.codegen.server.smithy.generators import org.junit.jupiter.api.Test import software.amazon.smithy.model.shapes.StructureShape -import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.implBlock import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.smithy.generators.StructureGenerator @@ -18,7 +17,6 @@ import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.lookup import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator -import software.amazon.smithy.rust.codegen.server.smithy.initializeInlineModuleWriter import software.amazon.smithy.rust.codegen.server.smithy.renderInlineMemoryModules import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext @@ -50,7 +48,7 @@ class ServerBuilderGeneratorTest { val builderGenerator = ServerBuilderGenerator( codegenContext, shape, - SmithyValidationExceptionConversionGenerator(codegenContext) + SmithyValidationExceptionConversionGenerator(codegenContext), ) builderGenerator.render(project, writer) @@ -63,15 +61,17 @@ class ServerBuilderGeneratorTest { } project.unitTest { - rust(""" - use super::*; - use crate::model::*; - let builder = Credentials::builder() - .username(Some("admin".to_owned())) - .password(Some("pswd".to_owned())) - .secret_key(Some("12345".to_owned())); - assert_eq!(format!("{:?}", builder), "Builder { username: Some(\"admin\"), password: \"*** Sensitive Data Redacted ***\", secret_key: \"*** Sensitive Data Redacted ***\" }"); - """) + rust( + """ + use super::*; + use crate::model::*; + let builder = Credentials::builder() + .username(Some("admin".to_owned())) + .password(Some("pswd".to_owned())) + .secret_key(Some("12345".to_owned())); + assert_eq!(format!("{:?}", builder), "Builder { username: Some(\"admin\"), password: \"*** Sensitive Data Redacted ***\", secret_key: \"*** Sensitive Data Redacted ***\" }"); + """, + ) } project.compileAndTest() } diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt index 7722851d1c..9661ccc105 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt @@ -14,8 +14,8 @@ import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.lookup import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule -import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.createTestInlineModuleCreator +import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.renderInlineMemoryModules import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverRenderWithModelBuilder import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext @@ -57,10 +57,12 @@ class UnconstrainedCollectionGeneratorTest { project.withModule(ServerRustModule.ConstrainedModule) { listOf(listA, listB).forEach { - PubCrateConstrainedCollectionGenerator(codegenContext, - //this, + PubCrateConstrainedCollectionGenerator( + codegenContext, + // this, this.createTestInlineModuleCreator(), - it).render() + it, + ).render() } } project.withModule(ServerRustModule.UnconstrainedModule) unconstrainedModuleWriter@{ diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt index 20d6e2e89e..c60d10d09f 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt @@ -15,8 +15,8 @@ import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.lookup import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule.Model -import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.createTestInlineModuleCreator +import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.renderInlineMemoryModules import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverRenderWithModelBuilder import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext @@ -60,16 +60,20 @@ class UnconstrainedMapGeneratorTest { project.withModule(ServerRustModule.ConstrainedModule) { listOf(mapA, mapB).forEach { - PubCrateConstrainedMapGenerator(codegenContext, + PubCrateConstrainedMapGenerator( + codegenContext, this.createTestInlineModuleCreator(), - it).render() + it, + ).render() } } project.withModule(ServerRustModule.UnconstrainedModule) unconstrainedModuleWriter@{ project.withModule(Model) modelsModuleWriter@{ listOf(mapA, mapB).forEach { - UnconstrainedMapGenerator(codegenContext, - this@unconstrainedModuleWriter.createTestInlineModuleCreator(), it).render() + UnconstrainedMapGenerator( + codegenContext, + this@unconstrainedModuleWriter.createTestInlineModuleCreator(), it, + ).render() MapConstraintViolationGenerator( codegenContext, diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt index 774b9110f0..bf1904757e 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt @@ -50,7 +50,7 @@ class UnconstrainedUnionGeneratorTest { project.withModule(ServerRustModule.Model) { UnionGenerator(model, symbolProvider, this, unionShape, renderUnknownVariant = false).render() } - + project.withModule(ServerRustModule.UnconstrainedModule) unconstrainedModuleWriter@{ project.withModule(ServerRustModule.Model) modelsModuleWriter@{ UnconstrainedUnionGenerator(codegenContext, project.createInlineModuleCreator(), this@modelsModuleWriter, unionShape).render() diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamUnmarshallerGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamUnmarshallerGeneratorTest.kt index 6a4b583936..3821fca909 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamUnmarshallerGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamUnmarshallerGeneratorTest.kt @@ -23,7 +23,6 @@ import software.amazon.smithy.rust.codegen.core.testutil.TestEventStreamProject import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.generators.serverBuilderSymbol -import software.amazon.smithy.rust.codegen.server.smithy.renderInlineMemoryModules import software.amazon.smithy.rust.codegen.server.smithy.transformers.ConstrainedMemberTransform class ServerEventStreamUnmarshallerGeneratorTest { From 3e276ac551a199f2e3f1149123f47a6891aa1dc0 Mon Sep 17 00:00:00 2001 From: Fahad Zubair Date: Fri, 17 Feb 2023 15:58:42 +0000 Subject: [PATCH 11/18] RustCrate need to be passed for server builder --- .../eventstream/ClientEventStreamBaseRequirements.kt | 1 + .../smithy/rust/codegen/server/smithy/Constraints.kt | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamBaseRequirements.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamBaseRequirements.kt index ff546f904f..7cb08314c2 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamBaseRequirements.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamBaseRequirements.kt @@ -75,6 +75,7 @@ abstract class ClientEventStreamBaseRequirements : EventStreamTestRequirements? { /** * Returns the parent and the inline module that this particular shape should go in. */ -fun Shape.getParentAndInlineModuleForConstrainedMember(symbolProvider: SymbolProvider, pubCrateServerBuilder: Boolean): Pair? { +fun Shape.getParentAndInlineModuleForConstrainedMember(symbolProvider: SymbolProvider, publicConstrainedTypes: Boolean): Pair? { val overriddenTrait = getTrait() ?: return null return if (overriddenTrait.container is StructureShape) { val structureModule = symbolProvider.toSymbol(overriddenTrait.container).module() - val builderModule = overriddenTrait.container.serverBuilderModule(symbolProvider, pubCrateServerBuilder) + val builderModule = overriddenTrait.container.serverBuilderModule(symbolProvider, !publicConstrainedTypes) Pair(structureModule, builderModule) } else { // For constrained member shapes, the ConstraintViolation code needs to go in an inline rust module // that is a descendant of the module that contains the extracted shape itself. - return if (!pubCrateServerBuilder) { + if (!publicConstrainedTypes) { // List, union and map types need to go into their own module val shapeSymbol = symbolProvider.toSymbol(this) val shapeModule = shapeSymbol.module() check(!shapeModule.parent.isInline()) { "Parent module of $id should not be an inline module" } + Pair(shapeModule.parent as RustModule.LeafModule, shapeModule) } else { val name = RustReservedWords.escapeIfNeeded(overriddenTrait.container.id.name).toSnakeCase() + "_internal" From 9522d576be665c818521f5b568d59b47ea64a7d3 Mon Sep 17 00:00:00 2001 From: Fahad Zubair Date: Fri, 17 Feb 2023 16:02:52 +0000 Subject: [PATCH 12/18] Param renamed in getParentAndInlineModuleForConstrainedMember --- .../amazon/smithy/rust/codegen/server/smithy/Constraints.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt index 87ca31845d..fb978230d0 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt @@ -191,7 +191,7 @@ fun Shape.getParentAndInlineModuleForConstrainedMember(symbolProvider: SymbolPro } else { // For constrained member shapes, the ConstraintViolation code needs to go in an inline rust module // that is a descendant of the module that contains the extracted shape itself. - if (!publicConstrainedTypes) { + if (publicConstrainedTypes) { // List, union and map types need to go into their own module val shapeSymbol = symbolProvider.toSymbol(this) val shapeModule = shapeSymbol.module() From 7539dcdf4ae7bfce76c379ef80c7d202d25a7a54 Mon Sep 17 00:00:00 2001 From: Fahad Zubair Date: Fri, 17 Feb 2023 16:33:36 +0000 Subject: [PATCH 13/18] pubCrate to publicConstrainedType rename --- .../smithy/ConstraintViolationSymbolProvider.kt | 10 +++------- .../rust/codegen/server/smithy/Constraints.kt | 7 +++---- .../smithy/RustCrateInlineModuleComposingWriter.kt | 14 +++++++------- .../smithy/UnconstrainedShapeSymbolProvider.kt | 2 +- .../UnconstrainedCollectionGeneratorTest.kt | 1 - 5 files changed, 14 insertions(+), 20 deletions(-) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt index 0543e48634..b47103aa75 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt @@ -81,12 +81,8 @@ class ConstraintViolationSymbolProvider( private fun Shape.shapeModule(): RustModule.LeafModule { val documentation = if (publicConstrainedTypes && this.isDirectlyConstrained(base)) { - if (this.hasTrait(SyntheticStructureFromConstrainedMemberTrait.ID)) { - val symbol = base.toSymbol(this) - "See [`${this.contextName(serviceShape)}`]($symbol)." - } else { - "See [`${this.contextName(serviceShape)}`]." - } + val symbol = base.toSymbol(this) + "See [`${this.contextName(serviceShape)}`]($symbol)." } else { null } @@ -96,7 +92,7 @@ class ConstraintViolationSymbolProvider( val (module, name) = if (syntheticTrait != null) { // For constrained member shapes, the ConstraintViolation code needs to go in an inline rust module // that is a descendant of the module that contains the extracted shape itself. - val overriddenMemberModule = this.getParentAndInlineModuleForConstrainedMember(base, !publicConstrainedTypes)!! + val overriddenMemberModule = this.getParentAndInlineModuleForConstrainedMember(base, publicConstrainedTypes)!! val name = syntheticTrait.member.memberName Pair(overriddenMemberModule.second, RustReservedWords.escapeIfNeeded(name).toSnakeCase()) } else { diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt index fb978230d0..aeb60d59de 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt @@ -191,14 +191,13 @@ fun Shape.getParentAndInlineModuleForConstrainedMember(symbolProvider: SymbolPro } else { // For constrained member shapes, the ConstraintViolation code needs to go in an inline rust module // that is a descendant of the module that contains the extracted shape itself. - if (publicConstrainedTypes) { - // List, union and map types need to go into their own module + return if (publicConstrainedTypes) { + // Non-structured shape types need to go into their own module. val shapeSymbol = symbolProvider.toSymbol(this) val shapeModule = shapeSymbol.module() check(!shapeModule.parent.isInline()) { - "Parent module of $id should not be an inline module" + "Parent module of $id should not be an inline module." } - Pair(shapeModule.parent as RustModule.LeafModule, shapeModule) } else { val name = RustReservedWords.escapeIfNeeded(overriddenTrait.container.id.name).toSnakeCase() + "_internal" diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt index ca4c575e91..39cc000913 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt @@ -55,7 +55,7 @@ fun RustCrate.withModuleOrWithStructureBuilderModule( ) { // All structure constrained-member-shapes code is generated inside the structure builder's module. val parentAndInlineModuleInfo = - shape.getParentAndInlineModuleForConstrainedMember(codegenContext.symbolProvider, !codegenContext.settings.codegenConfig.publicConstrainedTypes) + shape.getParentAndInlineModuleForConstrainedMember(codegenContext.symbolProvider, codegenContext.settings.codegenConfig.publicConstrainedTypes) if (parentAndInlineModuleInfo == null) { this.withModule(module, codeWritable) } else { @@ -83,7 +83,7 @@ fun RustCrate.useShapeWriterOrUseWithStructureBuilder( ) { // All structure constrained-member-shapes code is generated inside the structure builder's module. val parentAndInlineModuleInfo = - shape.getParentAndInlineModuleForConstrainedMember(codegenContext.symbolProvider, !codegenContext.settings.codegenConfig.publicConstrainedTypes) + shape.getParentAndInlineModuleForConstrainedMember(codegenContext.symbolProvider, codegenContext.settings.codegenConfig.publicConstrainedTypes) if (parentAndInlineModuleInfo == null) { docWriter?.invoke() this.useShapeWriter(shape, writable) @@ -180,7 +180,7 @@ class InnerModule(debugMode: Boolean) { if (hierarchy.isNotEmpty()) { val topMost = hierarchy.removeFirst() - // Create an intermediate writer for all inner modules in the hierarchy + // Create an intermediate writer for all inner modules in the hierarchy. rustCrate.withModule(topMost) { var writer = this hierarchy.forEach { @@ -271,18 +271,18 @@ class InnerModule(debugMode: Boolean) { renderDescendents(this, it.writer) } - // Add dependencies introduced by the inline module to the + // Add dependencies introduced by the inline module to the top most RustWriter. it.writer.dependencies.forEach { dep -> writerToAddDependencies!!.addDependency(dep) } } } // Go over all the top level modules, create an `inlineModule` on the `RustWriter` - // and call the descendent hierarchy renderer using the `inlineModule::RustWriter` + // and call the descendent hierarchy renderer using the `inlineModule::RustWriter`. topLevelModuleWriters.forEach { writerToAddDependencies = it check(inlineModuleWriters[it] != null) { - "There must be a registered RustWriter for this module" + "There must be a registered RustWriter for this module." } renderDescendents(it, it) @@ -328,7 +328,7 @@ class InnerModule(debugMode: Boolean) { inlineWriter } else { check(inlineModuleAndWriter.inlineModule == lookForModule) { - "the two inline modules have the same name but different attributes on them" + "The two inline modules have the same name but different attributes on them." } inlineModuleAndWriter.writer diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProvider.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProvider.kt index fc85f3e2b1..7b861c4659 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProvider.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProvider.kt @@ -100,7 +100,7 @@ class UnconstrainedShapeSymbolProvider( check(shape is CollectionShape || shape is MapShape || shape is UnionShape) val name = unconstrainedTypeNameForCollectionOrMapOrUnionShape(shape) - val parent = shape.getParentAndInlineModuleForConstrainedMember(this, !publicConstrainedTypes)?.second ?: ServerRustModule.UnconstrainedModule + val parent = shape.getParentAndInlineModuleForConstrainedMember(this, publicConstrainedTypes)?.second ?: ServerRustModule.UnconstrainedModule val module = RustModule.new( RustReservedWords.escapeIfNeeded(name.toSnakeCase()), diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt index 9661ccc105..28a8c1ef4c 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt @@ -59,7 +59,6 @@ class UnconstrainedCollectionGeneratorTest { listOf(listA, listB).forEach { PubCrateConstrainedCollectionGenerator( codegenContext, - // this, this.createTestInlineModuleCreator(), it, ).render() From 482ba38dc2cf6fbf24051b2da11438014577f4d8 Mon Sep 17 00:00:00 2001 From: Fahad Zubair Date: Fri, 17 Feb 2023 16:53:56 +0000 Subject: [PATCH 14/18] PythonServer symbol builder needed to pass publicConstrainedTypes --- .../server/python/smithy/RustServerCodegenPythonPlugin.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/RustServerCodegenPythonPlugin.kt b/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/RustServerCodegenPythonPlugin.kt index 19e3e0dba2..e5694a06cd 100644 --- a/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/RustServerCodegenPythonPlugin.kt +++ b/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/RustServerCodegenPythonPlugin.kt @@ -79,7 +79,7 @@ class RustServerCodegenPythonPlugin : SmithyBuildPlugin { // Generate public constrained types for directly constrained shapes. // In the Python server project, this is only done to generate constrained types for simple shapes (e.g. // a `string` shape with the `length` trait), but these always remain `pub(crate)`. - .let { if (constrainedTypes) ConstrainedShapeSymbolProvider(it, model, serviceShape) else it } + .let { if (constrainedTypes) ConstrainedShapeSymbolProvider(it, model, serviceShape, constrainedTypes) else it } // Generate different types for EventStream shapes (e.g. transcribe streaming) .let { EventStreamSymbolProvider(symbolVisitorConfig.runtimeConfig, it, model, CodegenTarget.SERVER) } // Add Rust attributes (like `#[derive(PartialEq)]`) to generated shapes From 40c6b4427e9bd79b8630536c6d56df239a0730fd Mon Sep 17 00:00:00 2001 From: Fahad Zubair Date: Fri, 17 Feb 2023 17:43:48 +0000 Subject: [PATCH 15/18] @required still remains on the member shape after transformation --- .../smithy/ConstraintsMemberShapeTest.kt | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt index 24249fa25e..959f81c625 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt @@ -5,13 +5,15 @@ package software.amazon.smithy.rust.codegen.server.smithy -import io.kotest.matchers.collections.shouldContain import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldNotBe import org.junit.jupiter.api.Test +import software.amazon.smithy.aws.traits.DataTrait import software.amazon.smithy.model.Model +import software.amazon.smithy.model.SourceLocation import software.amazon.smithy.model.shapes.ShapeId import software.amazon.smithy.model.traits.RequiredTrait +import software.amazon.smithy.model.traits.Trait 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 @@ -22,6 +24,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.transformers.OperationNor import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.generatePluginContext import software.amazon.smithy.rust.codegen.core.testutil.unitTest +import software.amazon.smithy.rust.codegen.core.util.expectTrait import software.amazon.smithy.rust.codegen.core.util.runCommand import software.amazon.smithy.rust.codegen.core.util.toPascalCase import software.amazon.smithy.rust.codegen.core.util.toSnakeCase @@ -265,7 +268,19 @@ class ConstraintsMemberShapeTest { outputModelOnly, "constrainedMemberShape.synthetic#OperationUsingGetOutput\$constrainedPatternString", "constrainedMemberShape#OperationUsingGetOutput\$constrainedPatternString", - "aws.api#data", + DataTrait("content", SourceLocation.NONE), + ) + } + + @Test + fun `required remains on constrained member shape`() { + val transformedModel = loadModel(outputModelOnly) + checkShapeHasTrait( + transformedModel, + outputModelOnly, + "constrainedMemberShape.synthetic#OperationUsingGetOutput\$requiredConstrainedString", + "constrainedMemberShape#OperationUsingGetOutput\$requiredConstrainedString", + RequiredTrait(), ) } @@ -467,17 +482,15 @@ class ConstraintsMemberShapeTest { orgModel: Model, member: String, orgModelMember: String, - traitName: String, + trait: Trait, ) { val memberId = ShapeId.from(member) val memberShape = model.expectShape(memberId).asMemberShape().get() val orgMemberShape = orgModel.expectShape(ShapeId.from(orgModelMember)).asMemberShape().get() - memberShape.allTraits.keys shouldContain ShapeId.from(traitName) - orgMemberShape.allTraits.keys shouldContain ShapeId.from(traitName) + val newMemberTrait = memberShape.expectTrait(trait::class.java) + val oldMemberTrait = orgMemberShape.expectTrait(trait::class.java) - val newMemberTrait = memberShape.allTraits[ShapeId.from(traitName)] - val oldMemberTrait = orgMemberShape.allTraits[ShapeId.from(traitName)] newMemberTrait shouldBe oldMemberTrait } } From 9f402914ac7ac0b18957618c1f36bf8813565a9d Mon Sep 17 00:00:00 2001 From: Fahad Zubair Date: Fri, 17 Feb 2023 18:19:21 +0000 Subject: [PATCH 16/18] ConcurrentLinkedQueue used for root RustWriters --- .../server/smithy/RustCrateInlineModuleComposingWriter.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt index 39cc000913..c668534a26 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt @@ -13,6 +13,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.Writable import software.amazon.smithy.rust.codegen.core.smithy.RustCrate import software.amazon.smithy.rust.codegen.core.smithy.module import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.ConcurrentLinkedQueue typealias DocWriter = () -> Any typealias InlineModuleCreator = (Symbol, Writable) -> Unit @@ -144,7 +145,8 @@ private val crateToInlineModule: ConcurrentHashMap = ConcurrentHashMap() class InnerModule(debugMode: Boolean) { - private val topLevelModuleWriters: MutableSet = mutableSetOf() + // Holds the root modules to start rendering the descendents from. + private val topLevelModuleWriters: ConcurrentLinkedQueue = ConcurrentLinkedQueue() private val inlineModuleWriters: ConcurrentHashMap> = ConcurrentHashMap() private val docWriters: ConcurrentHashMap> = ConcurrentHashMap() private val writerCreator = RustWriter.factory(debugMode) From 1260efccb1aa4ee70228df3a0c64a5ae5a21ca05 Mon Sep 17 00:00:00 2001 From: Fahad Zubair Date: Fri, 17 Feb 2023 18:49:53 +0000 Subject: [PATCH 17/18] runTestCase does not run the tests but just sets them up, hence has been renamed --- .../ClientEventStreamMarshallerGeneratorTest.kt | 2 +- .../ClientEventStreamUnmarshallerGeneratorTest.kt | 2 +- .../codegen/core/testutil/EventStreamTestTools.kt | 4 +--- .../smithy/RustCrateInlineModuleComposingWriter.kt | 12 ++++++++---- .../server/smithy/ConstraintsMemberShapeTest.kt | 1 - .../RustCrateInlineModuleComposingWriterTest.kt | 1 - .../ServerEventStreamMarshallerGeneratorTest.kt | 2 +- .../ServerEventStreamUnmarshallerGeneratorTest.kt | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamMarshallerGeneratorTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamMarshallerGeneratorTest.kt index 6249be524a..b73d12a8d8 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamMarshallerGeneratorTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamMarshallerGeneratorTest.kt @@ -23,7 +23,7 @@ class ClientEventStreamMarshallerGeneratorTest { @ParameterizedTest @ArgumentsSource(TestCasesProvider::class) fun test(testCase: EventStreamTestModels.TestCase) { - EventStreamTestTools.runTestCase( + EventStreamTestTools.setupTestCase( testCase, object : ClientEventStreamBaseRequirements() { override fun renderGenerator( diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamUnmarshallerGeneratorTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamUnmarshallerGeneratorTest.kt index f505747af7..b20810ef97 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamUnmarshallerGeneratorTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamUnmarshallerGeneratorTest.kt @@ -25,7 +25,7 @@ class ClientEventStreamUnmarshallerGeneratorTest { @ParameterizedTest @ArgumentsSource(TestCasesProvider::class) fun test(testCase: EventStreamTestModels.TestCase) { - EventStreamTestTools.runTestCase( + EventStreamTestTools.setupTestCase( testCase, object : ClientEventStreamBaseRequirements() { override fun renderGenerator( diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamTestTools.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamTestTools.kt index 1529715a7a..4cfebd3242 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamTestTools.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamTestTools.kt @@ -82,7 +82,7 @@ interface EventStreamTestRequirements { } object EventStreamTestTools { - fun runTestCase( + fun setupTestCase( testCase: EventStreamTestModels.TestCase, requirements: EventStreamTestRequirements, codegenTarget: CodegenTarget, @@ -111,8 +111,6 @@ object EventStreamTestTools { } } - println(testCase.model.toString()) - return test.project } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt index c668534a26..f4f352260e 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriter.kt @@ -13,7 +13,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.Writable import software.amazon.smithy.rust.codegen.core.smithy.RustCrate import software.amazon.smithy.rust.codegen.core.smithy.module import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.ConcurrentLinkedQueue typealias DocWriter = () -> Any typealias InlineModuleCreator = (Symbol, Writable) -> Unit @@ -146,10 +145,15 @@ private val crateToInlineModule: ConcurrentHashMap = class InnerModule(debugMode: Boolean) { // Holds the root modules to start rendering the descendents from. - private val topLevelModuleWriters: ConcurrentLinkedQueue = ConcurrentLinkedQueue() + private val topLevelModuleWriters: ConcurrentHashMap = ConcurrentHashMap() private val inlineModuleWriters: ConcurrentHashMap> = ConcurrentHashMap() private val docWriters: ConcurrentHashMap> = ConcurrentHashMap() private val writerCreator = RustWriter.factory(debugMode) + + // By default, when a RustWriter is rendered, it prints a comment on top + // indicating that it contains generated code and should not be manually edited. This comment + // appears on each descendent inline module. To remove those comments, each time an inline + // module is rendered, first `emptyLineCount` characters are removed from it. private val emptyLineCount: Int = writerCreator .apply("lines-it-always-writes.rs", "crate") .toString() @@ -280,7 +284,7 @@ class InnerModule(debugMode: Boolean) { // Go over all the top level modules, create an `inlineModule` on the `RustWriter` // and call the descendent hierarchy renderer using the `inlineModule::RustWriter`. - topLevelModuleWriters.forEach { + topLevelModuleWriters.keys.forEach { writerToAddDependencies = it check(inlineModuleWriters[it] != null) { @@ -309,7 +313,7 @@ class InnerModule(debugMode: Boolean) { * Records the root of a dependency graph of inline modules. */ private fun registerTopMostWriter(outerWriter: RustWriter): MutableList { - topLevelModuleWriters.add(outerWriter) + topLevelModuleWriters[outerWriter] = Unit return inlineModuleWriters.getOrPut(outerWriter) { mutableListOf() } } diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt index 959f81c625..5d29d109a3 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintsMemberShapeTest.kt @@ -24,7 +24,6 @@ import software.amazon.smithy.rust.codegen.core.smithy.transformers.OperationNor import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.generatePluginContext import software.amazon.smithy.rust.codegen.core.testutil.unitTest -import software.amazon.smithy.rust.codegen.core.util.expectTrait import software.amazon.smithy.rust.codegen.core.util.runCommand import software.amazon.smithy.rust.codegen.core.util.toPascalCase import software.amazon.smithy.rust.codegen.core.util.toSnakeCase diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt index 2fbebee1cf..3637548d9a 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustCrateInlineModuleComposingWriterTest.kt @@ -92,7 +92,6 @@ class RustCrateInlineModuleComposingWriterTest { private fun helloWorld(writer: RustWriter, moduleName: String) { writer.rustBlock("pub fn hello_world()") { writer.comment("Module $moduleName") - writer.rust("""println!("from inside $moduleName");""") } } diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamMarshallerGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamMarshallerGeneratorTest.kt index abbf0b4145..cf0c4f94b1 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamMarshallerGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamMarshallerGeneratorTest.kt @@ -23,7 +23,7 @@ class ServerEventStreamMarshallerGeneratorTest { @ParameterizedTest @ArgumentsSource(TestCasesProvider::class) fun test(testCase: TestCase) { - val testProject = EventStreamTestTools.runTestCase( + val testProject = EventStreamTestTools.setupTestCase( testCase.eventStreamTestCase, object : ServerEventStreamBaseRequirements() { override val publicConstrainedTypes: Boolean get() = testCase.publicConstrainedTypes diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamUnmarshallerGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamUnmarshallerGeneratorTest.kt index 3821fca909..fa16322fe9 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamUnmarshallerGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamUnmarshallerGeneratorTest.kt @@ -35,7 +35,7 @@ class ServerEventStreamUnmarshallerGeneratorTest { return } - val testProject = EventStreamTestTools.runTestCase( + val testProject = EventStreamTestTools.setupTestCase( testCase.eventStreamTestCase, object : ServerEventStreamBaseRequirements() { override val publicConstrainedTypes: Boolean get() = testCase.publicConstrainedTypes From 0fcc40a95d8b0d66616ae09e348a9e2804832c7c Mon Sep 17 00:00:00 2001 From: Fahad Zubair Date: Fri, 17 Feb 2023 18:52:58 +0000 Subject: [PATCH 18/18] CHANGELOG added --- CHANGELOG.next.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index b206c8c663..94f928a407 100644 --- a/CHANGELOG.next.toml +++ b/CHANGELOG.next.toml @@ -210,3 +210,9 @@ message = "Fix issue where clients using native-tls connector were prevented fro references = ["aws-sdk-rust#736"] meta = { "breaking" = false, "tada" = false, "bug" = true, "target" = "client" } author = "Velfi" + +[[smithy-rs]] +message = "Support for constraint traits on member shapes (constraint trait precedence)" +references = ["smithy-rs#1969"] +meta = { "breaking" = false, "tada" = true, "bug" = false, "target" = "server" } +author = "drganjoo"