Unverified Commit 3d61226b authored by Russell Cohen's avatar Russell Cohen Committed by GitHub
Browse files

fix and test a number of codegen bugs (#539)

- fields named `build`, `send`, `default`
- operations named keywords
- single-element unions needed a clippy lint ignored
- enum docs needed `escape` to be invoked
parent 398ac413
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ import software.amazon.smithy.rust.codegen.rustlang.CargoDependency
import software.amazon.smithy.rust.codegen.rustlang.Feature
import software.amazon.smithy.rust.codegen.rustlang.RustMetadata
import software.amazon.smithy.rust.codegen.rustlang.RustModule
import software.amazon.smithy.rust.codegen.rustlang.RustReservedWords
import software.amazon.smithy.rust.codegen.rustlang.RustType
import software.amazon.smithy.rust.codegen.rustlang.RustWriter
import software.amazon.smithy.rust.codegen.rustlang.asOptional
@@ -139,7 +140,7 @@ class FluentClientGenerator(protocolConfig: ProtocolConfig) {
                val name = symbolProvider.toSymbol(operation).name
                rust(
                    """
                    pub fn ${name.toSnakeCase()}(&self) -> fluent_builders::$name<C> {
                    pub fn ${RustReservedWords.escapeIfNeeded(name.toSnakeCase())}(&self) -> fluent_builders::$name<C> {
                        fluent_builders::$name::new(self.handle.clone())
                    }"""
                )
+10 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ service Config {
       ErrCollisions,
       Result,
       Option,
       Match
    ]
}

@@ -38,6 +39,11 @@ operation ReservedWordsAsMembers {
    input: ReservedWords
}

// tests that module names are properly escaped
operation Match {
    input: ReservedWords
}


structure ReservedWords {
    as: Integer,
@@ -45,7 +51,10 @@ structure ReservedWords {
    enum: UnknownVariantCollidingEnum,
    self: Boolean,
    crate: Boolean,
    super: Boolean
    super: Boolean,
    build: String,
    default: String,
    send: String
}

@httpRequestTests([
+6 −1
Original line number Diff line number Diff line
@@ -200,7 +200,7 @@ operation MapWithEnumKeyOp {


@enum([
    { value: "has\"quotes", name: "HAS_QUOTES" },
    { value: "has\"quotes", name: "HAS_QUOTES", documentation: "this needs#tobe escaped" },
    { value: "normal", name: "NORMAL" },
])
string EnumWithEscapedChars
@@ -245,9 +245,14 @@ map NonSparseMap {
    value: String,
}

union SingleElementUnion {
    a: String
}

structure NullInNonSparseOutput {
    list: NonSparseList,
    map: NonSparseMap,
    union: SingleElementUnion
}

@http(uri: "/null-in-non-sparse", method: "POST")
+14 −3
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ import software.amazon.smithy.model.traits.EnumDefinition
import software.amazon.smithy.rust.codegen.smithy.MaybeRenamed
import software.amazon.smithy.rust.codegen.smithy.RustSymbolProvider
import software.amazon.smithy.rust.codegen.smithy.WrappingSymbolProvider
import software.amazon.smithy.rust.codegen.util.orNull
import software.amazon.smithy.rust.codegen.util.toPascalCase

class RustReservedWordSymbolProvider(private val base: RustSymbolProvider) : WrappingSymbolProvider(base) {
@@ -21,7 +22,12 @@ class RustReservedWordSymbolProvider(private val base: RustSymbolProvider) : Wra
        ReservedWordSymbolProvider.builder().symbolProvider(base).memberReservedWords(RustReservedWords).build()

    override fun toMemberName(shape: MemberShape): String {
        return internal.toMemberName(shape)
        return when (val baseName = internal.toMemberName(shape)) {
            "build" -> "build_value"
            "default" -> "default_value"
            "send" -> "send_value"
            else -> baseName
        }
    }

    override fun toSymbol(shape: Shape): Symbol {
@@ -30,8 +36,8 @@ class RustReservedWordSymbolProvider(private val base: RustSymbolProvider) : Wra

    override fun toEnumVariantName(definition: EnumDefinition): MaybeRenamed? {
        val baseName = base.toEnumVariantName(definition) ?: return null
        check(baseName.name.toPascalCase() == baseName.name) {
            "Enum variants must already be in pascal case"
        check(definition.name.orNull()?.toPascalCase() == baseName.name) {
            "Enum variants must already be in pascal case ${baseName.name} differed from ${baseName.name.toPascalCase()}. Definition: ${definition.name}"
        }
        check(baseName.renamedFrom == null) {
            "definitions should only pass through the renamer once"
@@ -115,5 +121,10 @@ object RustReservedWords : ReservedWords {
        else -> "r##$word"
    }

    fun escapeIfNeeded(word: String): String = when (isReserved(word)) {
        true -> escape(word)
        else -> word
    }

    override fun isReserved(word: String): Boolean = RustKeywords.contains(word)
}
+3 −1
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ import software.amazon.smithy.model.Model
import software.amazon.smithy.model.shapes.MemberShape
import software.amazon.smithy.model.shapes.StructureShape
import software.amazon.smithy.rust.codegen.rustlang.Attribute
import software.amazon.smithy.rust.codegen.rustlang.RustReservedWords
import software.amazon.smithy.rust.codegen.rustlang.RustType
import software.amazon.smithy.rust.codegen.rustlang.RustWriter
import software.amazon.smithy.rust.codegen.rustlang.asOptional
@@ -34,7 +35,8 @@ import software.amazon.smithy.rust.codegen.util.toSnakeCase

fun StructureShape.builderSymbol(symbolProvider: RustSymbolProvider): RuntimeType {
    val symbol = symbolProvider.toSymbol(this)
    return RuntimeType("Builder", null, "${symbol.namespace}::${symbol.name.toSnakeCase()}")
    val builderNamespace = RustReservedWords.escapeIfNeeded(symbol.name.toSnakeCase())
    return RuntimeType("Builder", null, "${symbol.namespace}::$builderNamespace")
}

fun RuntimeConfig.operationBuildError() = RuntimeType.operationModule(this).member("BuildError")
Loading