From 08c16d31cbc74f09ab9547529bc00bca58af6ae2 Mon Sep 17 00:00:00 2001 From: John DiSanti Date: Wed, 22 Feb 2023 15:37:32 -0800 Subject: [PATCH] Fix escaping of `Self` in symbol providers (#2381) * Fix escaping of `Self` in symbol providers * Clean up an old hack --- .../core/rustlang/RustReservedWords.kt | 36 ++++++++++--------- .../core/rustlang/RustReservedWordsTest.kt | 14 +++++++- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustReservedWords.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustReservedWords.kt index 197033c0fe..51c03b5b10 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustReservedWords.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustReservedWords.kt @@ -23,7 +23,10 @@ import software.amazon.smithy.rust.codegen.core.util.letIf class RustReservedWordSymbolProvider(private val base: RustSymbolProvider) : WrappingSymbolProvider(base) { private val internal = - ReservedWordSymbolProvider.builder().symbolProvider(base).memberReservedWords(RustReservedWords).build() + ReservedWordSymbolProvider.builder().symbolProvider(base) + .nameReservedWords(RustReservedWords) + .memberReservedWords(RustReservedWords) + .build() override fun toMemberName(shape: MemberShape): String { val baseName = super.toMemberName(shape) @@ -49,20 +52,10 @@ class RustReservedWordSymbolProvider(private val base: RustSymbolProvider) : Wra // that represent union variants that have been added since this SDK was generated. UnionGenerator.UnknownVariantName -> "${UnionGenerator.UnknownVariantName}Value" "${UnionGenerator.UnknownVariantName}Value" -> "${UnionGenerator.UnknownVariantName}Value_" - // Self cannot be used as a raw identifier, so we can't use the normal escaping strategy - // https://internals.rust-lang.org/t/raw-identifiers-dont-work-for-all-identifiers/9094/4 - "Self" -> "SelfValue" - // Real models won't end in `_` so it's safe to stop here - "SelfValue" -> "SelfValue_" else -> reservedWordReplacedName } container is EnumShape || container.hasTrait() -> when (baseName) { - // Self cannot be used as a raw identifier, so we can't use the normal escaping strategy - // https://internals.rust-lang.org/t/raw-identifiers-dont-work-for-all-identifiers/9094/4 - "Self" -> "SelfValue" - // Real models won't end in `_` so it's safe to stop here - "SelfValue" -> "SelfValue_" // Unknown is used as the name of the variant containing unexpected values "Unknown" -> "UnknownValue" // Real models won't end in `_` so it's safe to stop here @@ -103,7 +96,7 @@ class RustReservedWordSymbolProvider(private val base: RustSymbolProvider) : Wra }.build() } - else -> base.toSymbol(shape) + else -> renamedSymbol } } } @@ -165,11 +158,20 @@ object RustReservedWords : ReservedWords { "try", ) - private val cantBeRaw = setOf("self", "crate", "super") + // Some things can't be used as a raw identifier, so we can't use the normal escaping strategy + // https://internals.rust-lang.org/t/raw-identifiers-dont-work-for-all-identifiers/9094/4 + private val keywordEscapingMap = mapOf( + "crate" to "crate_", + "super" to "super_", + "self" to "self_", + "Self" to "SelfValue", + // Real models won't end in `_` so it's safe to stop here + "SelfValue" to "SelfValue_", + ) - override fun escape(word: String): String = when { - cantBeRaw.contains(word) -> "${word}_" - else -> "r##$word" + override fun escape(word: String): String = when (val mapped = keywordEscapingMap[word]) { + null -> "r##$word" + else -> mapped } fun escapeIfNeeded(word: String): String = when (isReserved(word)) { @@ -177,5 +179,5 @@ object RustReservedWords : ReservedWords { else -> word } - override fun isReserved(word: String): Boolean = RustKeywords.contains(word) + override fun isReserved(word: String): Boolean = RustKeywords.contains(word) || keywordEscapingMap.contains(word) } diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustReservedWordsTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustReservedWordsTest.kt index 4a715aeb9e..563dc2f454 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustReservedWordsTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustReservedWordsTest.kt @@ -16,11 +16,23 @@ import software.amazon.smithy.rust.codegen.core.smithy.WrappingSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.renamedFrom import software.amazon.smithy.rust.codegen.core.testutil.TestRustSymbolProviderConfig import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel +import software.amazon.smithy.rust.codegen.core.util.lookup internal class RustReservedWordSymbolProviderTest { private class TestSymbolProvider(model: Model) : WrappingSymbolProvider(SymbolVisitor(model, null, TestRustSymbolProviderConfig)) + @Test + fun `structs are escaped`() { + val model = """ + namespace test + structure Self {} + """.asSmithyModel() + val provider = RustReservedWordSymbolProvider(TestSymbolProvider(model)) + val symbol = provider.toSymbol(model.lookup("test#Self")) + symbol.name shouldBe "SelfValue" + } + @Test fun `member names are escaped`() { val model = """ @@ -28,7 +40,7 @@ internal class RustReservedWordSymbolProviderTest { structure container { async: String } - """.trimMargin().asSmithyModel() + """.asSmithyModel() val provider = RustReservedWordSymbolProvider(TestSymbolProvider(model)) provider.toMemberName( MemberShape.builder().id("namespace#container\$async").target("namespace#Integer").build(),