From 01abf5522787948a05e9b0d659f128d70cb1579a Mon Sep 17 00:00:00 2001 From: Mayokun Yusuf Date: Sat, 24 Oct 2026 13:57:55 +0100 Subject: [PATCH] Emit nested qualifier annotations as instantiation expressions --- .../moshi/kotlin/codegen/api/DelegateKey.kt | 2 +- .../moshi/kotlin/codegen/ksp/KspUtil.kt | 4 +- .../ksp/JsonClassSymbolProcessorTest.kt | 41 +++++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/DelegateKey.kt b/moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/DelegateKey.kt index cba19b3cf..77220569a 100644 --- a/moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/DelegateKey.kt +++ b/moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/DelegateKey.kt @@ -80,7 +80,7 @@ public data class DelegateKey( } } -private fun AnnotationSpec.asInstantiationExpression(): CodeBlock { +internal fun AnnotationSpec.asInstantiationExpression(): CodeBlock { // (args) return CodeBlock.of("%T(%L)", typeName, members.joinToCode()) } diff --git a/moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/ksp/KspUtil.kt b/moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/ksp/KspUtil.kt index 4c994e6b9..526d1a350 100644 --- a/moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/ksp/KspUtil.kt +++ b/moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/ksp/KspUtil.kt @@ -29,6 +29,7 @@ import com.google.devtools.ksp.symbol.Origin.KOTLIN_LIB import com.squareup.kotlinpoet.AnnotationSpec import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.ksp.toClassName +import com.squareup.moshi.kotlin.codegen.api.asInstantiationExpression internal fun KSClassDeclaration.asType() = asType(emptyList()) @@ -106,7 +107,8 @@ private fun addValueToBlock( } } - is KSAnnotation -> member.add("%L", value.toAnnotationSpec(resolver)) + is KSAnnotation -> + member.add("%L", value.toAnnotationSpec(resolver).asInstantiationExpression()) else -> member.add(memberForValue(value)) } diff --git a/moshi-kotlin-codegen/src/test/java/com/squareup/moshi/kotlin/codegen/ksp/JsonClassSymbolProcessorTest.kt b/moshi-kotlin-codegen/src/test/java/com/squareup/moshi/kotlin/codegen/ksp/JsonClassSymbolProcessorTest.kt index bad93a333..2578a6f5e 100644 --- a/moshi-kotlin-codegen/src/test/java/com/squareup/moshi/kotlin/codegen/ksp/JsonClassSymbolProcessorTest.kt +++ b/moshi-kotlin-codegen/src/test/java/com/squareup/moshi/kotlin/codegen/ksp/JsonClassSymbolProcessorTest.kt @@ -521,6 +521,47 @@ class JsonClassSymbolProcessorTest { assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) } + @Test + fun qualifierWithNestedAnnotations() { + val result = + compile( + kotlin( + "source.kt", + """ + package test + import com.squareup.moshi.JsonClass + import com.squareup.moshi.JsonQualifier + import kotlin.annotation.AnnotationRetention.RUNTIME + import kotlin.annotation.AnnotationTarget.FIELD + import kotlin.annotation.Retention + import kotlin.annotation.Target + + @JsonClass(generateAdapter = true) + class TestAdapterClass( + @OuterAnnotation( + InnerAnnotation("first"), + InnerAnnotation("second"), + InnerAnnotation("third"), + ) + var param: String + ) + + @JsonQualifier + @Retention(RUNTIME) + @Target(FIELD) + annotation class OuterAnnotation( + vararg val values: InnerAnnotation + ) + + @Retention(RUNTIME) + @Target(FIELD) + annotation class InnerAnnotation(val name: String) + """, + ) + ) + assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) + } + @Test fun nonRuntimeQualifier() { val result =