From 5d0a951f214345ef2d5efa0a8197a78a93842968 Mon Sep 17 00:00:00 2001 From: Daniel Lin Date: Sat, 7 May 2022 23:11:09 -0400 Subject: [PATCH 1/3] Work around KT-52315 https://youtrack.jetbrains.com/issue/KT-52315 `header` and `impl` are deprecated and do not behave as modifier keywords anymore... except in this specific case, seemingly. --- .../java/com/squareup/kotlinpoet/TypeSpec.kt | 7 +++- .../com/squareup/kotlinpoet/TypeSpecTest.kt | 37 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeSpec.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeSpec.kt index 9e6a3c06b7..b803615ce2 100644 --- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeSpec.kt +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeSpec.kt @@ -115,7 +115,12 @@ public class TypeSpec private constructor( if (enumName != null) { codeWriter.emitKdoc(kdocWithConstructorParameters()) codeWriter.emitAnnotations(annotationSpecs, false) - codeWriter.emitCode("%N", enumName) + // These aren't keywords anymore but still break if unquoted. https://youtrack.jetbrains.com/issue/KT-52315 + if ((enumName == "header" || enumName == "impl") && superclassConstructorParametersBlock.isNotEmpty()) { + codeWriter.emitCode("`$enumName`") + } else { + codeWriter.emitCode("%N", enumName) + } if (superclassConstructorParametersBlock.isNotEmpty()) { codeWriter.emit("(") codeWriter.emitCode(superclassConstructorParametersBlock) diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeSpecTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeSpecTest.kt index a0334e3de4..5749674407 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeSpecTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeSpecTest.kt @@ -4898,6 +4898,43 @@ class TypeSpecTest { ) } + // https://youtrack.jetbrains.com/issue/KT-52315 + @Test fun escapeEnumConstantNamesWithConstructors() { + val primaryConstructor = FunSpec.constructorBuilder() + .addParameter("int", Int::class) + .build() + val enum = TypeSpec + .enumBuilder("MyEnum") + .primaryConstructor(primaryConstructor) + .addEnumConstant( + "header", + TypeSpec.anonymousClassBuilder() + .addSuperclassConstructorParameter("%L", 1) + .build() + ) + .addEnumConstant( + "impl", + TypeSpec.anonymousClassBuilder() + .addSuperclassConstructorParameter("%L", 2) + .build() + ) + .build() + assertThat(toString(enum)).isEqualTo( + """ + |package com.squareup.tacos + | + |import kotlin.Int + | + |public enum class MyEnum( + | int: Int, + |) { + | `header`(1), + | `impl`(2), + |} + |""".trimMargin() + ) + } + @Test fun escapeClassNames() { val type = TypeSpec.classBuilder("fun").build() assertThat(type.toString()).isEqualTo( From 2437dbc5ed8d42eadc31ab96db74c5f8907a7565 Mon Sep 17 00:00:00 2001 From: Daniel Lin Date: Mon, 9 May 2022 11:54:16 -0400 Subject: [PATCH 2/3] Simpler approach (escape everywhere) --- .../src/main/java/com/squareup/kotlinpoet/TypeSpec.kt | 7 +------ kotlinpoet/src/main/java/com/squareup/kotlinpoet/Util.kt | 4 ++++ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeSpec.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeSpec.kt index b803615ce2..9e6a3c06b7 100644 --- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeSpec.kt +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeSpec.kt @@ -115,12 +115,7 @@ public class TypeSpec private constructor( if (enumName != null) { codeWriter.emitKdoc(kdocWithConstructorParameters()) codeWriter.emitAnnotations(annotationSpecs, false) - // These aren't keywords anymore but still break if unquoted. https://youtrack.jetbrains.com/issue/KT-52315 - if ((enumName == "header" || enumName == "impl") && superclassConstructorParametersBlock.isNotEmpty()) { - codeWriter.emitCode("`$enumName`") - } else { - codeWriter.emitCode("%N", enumName) - } + codeWriter.emitCode("%N", enumName) if (superclassConstructorParametersBlock.isNotEmpty()) { codeWriter.emit("(") codeWriter.emitCode(superclassConstructorParametersBlock) diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Util.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Util.kt index 7bee9fd80f..cebb46cccb 100644 --- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Util.kt +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Util.kt @@ -248,6 +248,10 @@ private val KEYWORDS = setOf( "value", "vararg", + // These aren't keywords anymore but still break some code if unescaped. https://youtrack.jetbrains.com/issue/KT-52315 + "header", + "impl", + // Other reserved keywords "yield", ) From 75a3e7258debbd493f78c28eded80e9ce0d43469 Mon Sep 17 00:00:00 2001 From: Daniel Lin Date: Mon, 9 May 2022 12:33:46 -0400 Subject: [PATCH 3/3] Rename test function to be more specific Co-authored-by: Egor Andreevich --- .../src/test/java/com/squareup/kotlinpoet/TypeSpecTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeSpecTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeSpecTest.kt index 5749674407..327416a9e9 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeSpecTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeSpecTest.kt @@ -4899,7 +4899,7 @@ class TypeSpecTest { } // https://youtrack.jetbrains.com/issue/KT-52315 - @Test fun escapeEnumConstantNamesWithConstructors() { + @Test fun escapeHeaderAndImplAsEnumConstantNames() { val primaryConstructor = FunSpec.constructorBuilder() .addParameter("int", Int::class) .build()