diff --git a/moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/apt/metadata.kt b/moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/apt/metadata.kt index cccc7bbf7..79b95f4a6 100644 --- a/moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/apt/metadata.kt +++ b/moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/apt/metadata.kt @@ -332,7 +332,13 @@ private fun resolveTypeArgs( ): TypeName { val unwrappedType = propertyType.unwrapTypeAlias() - if (unwrappedType !is TypeVariableName) { + if (unwrappedType is ParameterizedTypeName) { + return unwrappedType.copy( + typeArguments = unwrappedType.typeArguments.map { + resolveTypeArgs(targetClass, it, resolvedTypes, allowedTypeVars, entryStartIndex) + }, + ) + } else if (unwrappedType !is TypeVariableName) { return unwrappedType } else if (entryStartIndex == -1) { return unwrappedType diff --git a/moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/ksp/TargetTypes.kt b/moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/ksp/TargetTypes.kt index 7f5aa8643..30f5e43a4 100644 --- a/moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/ksp/TargetTypes.kt +++ b/moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/ksp/TargetTypes.kt @@ -228,7 +228,9 @@ private fun declaredProperties( val result = mutableMapOf() for (property in classDecl.getDeclaredProperties()) { val initialType = property.type.resolve() - val resolvedType = if (initialType.declaration is KSTypeParameter) { + val resolvedType = if (initialType.declaration is KSTypeParameter || + initialType.arguments.any { it.type?.resolve()?.declaration is KSTypeParameter } + ) { property.asMemberOf(originalType.asType()) } else { initialType diff --git a/moshi-kotlin-codegen/src/test/java/com/squareup/moshi/kotlin/codegen/apt/JsonClassCodegenProcessorTest.kt b/moshi-kotlin-codegen/src/test/java/com/squareup/moshi/kotlin/codegen/apt/JsonClassCodegenProcessorTest.kt index b39b29d9e..46cf4c432 100644 --- a/moshi-kotlin-codegen/src/test/java/com/squareup/moshi/kotlin/codegen/apt/JsonClassCodegenProcessorTest.kt +++ b/moshi-kotlin-codegen/src/test/java/com/squareup/moshi/kotlin/codegen/apt/JsonClassCodegenProcessorTest.kt @@ -510,6 +510,28 @@ class JsonClassCodegenProcessorTest { assertThat(result.messages).contains("JsonQualifier @UpperCase must have RUNTIME retention") } + @Test + fun genericSuperClassPropertyTypeSubstitution() { + val result = compile( + kotlin( + "source.kt", + """ + package test + import com.squareup.moshi.JsonClass + + open class GenericSuperClass { + var t: T? = null + var list: List? = null + } + + @JsonClass(generateAdapter = true) + class SubClassOfGeneric : GenericSuperClass() + """, + ), + ) + assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) + } + @Test fun `TypeAliases with the same backing type should share the same adapter`() { val result = compile( 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 37966a870..0d540362d 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 @@ -557,6 +557,28 @@ class JsonClassSymbolProcessorTest { assertThat(result.messages).contains("Error preparing ElementEnvelope") } + @Test + fun genericSuperClassPropertyTypeSubstitution() { + val result = compile( + kotlin( + "source.kt", + """ + package test + import com.squareup.moshi.JsonClass + + open class GenericSuperClass { + var t: T? = null + var list: List? = null + } + + @JsonClass(generateAdapter = true) + class SubClassOfGeneric : GenericSuperClass() + """, + ), + ) + assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) + } + @Test fun `TypeAliases with the same backing type should share the same adapter`() { val result = compile(