diff --git a/interop/ksp/src/main/kotlin/com/squareup/kotlinpoet/ksp/KsTypes.kt b/interop/ksp/src/main/kotlin/com/squareup/kotlinpoet/ksp/KsTypes.kt index 0572b73960..a034fb62eb 100644 --- a/interop/ksp/src/main/kotlin/com/squareup/kotlinpoet/ksp/KsTypes.kt +++ b/interop/ksp/src/main/kotlin/com/squareup/kotlinpoet/ksp/KsTypes.kt @@ -15,7 +15,6 @@ */ package com.squareup.kotlinpoet.ksp -import com.google.devtools.ksp.symbol.ClassKind import com.google.devtools.ksp.symbol.KSClassDeclaration import com.google.devtools.ksp.symbol.KSType import com.google.devtools.ksp.symbol.KSTypeAlias @@ -64,12 +63,6 @@ internal fun KSType.toTypeName( } val type = when (val decl = declaration) { is KSClassDeclaration -> { - val arguments = if (decl.classKind == ClassKind.ANNOTATION_CLASS) { - arguments - } else { - typeArguments - } - decl.toClassName().withTypeArguments(arguments.map { it.toTypeName(typeParamResolver) }) } is KSTypeParameter -> typeParamResolver[decl.name.getShortName()] diff --git a/interop/ksp/test-processor/src/main/kotlin/com/squareup/kotlinpoet/ksp/test/processor/TestProcessor.kt b/interop/ksp/test-processor/src/main/kotlin/com/squareup/kotlinpoet/ksp/test/processor/TestProcessor.kt index b1d41d4032..036a64b6b2 100644 --- a/interop/ksp/test-processor/src/main/kotlin/com/squareup/kotlinpoet/ksp/test/processor/TestProcessor.kt +++ b/interop/ksp/test-processor/src/main/kotlin/com/squareup/kotlinpoet/ksp/test/processor/TestProcessor.kt @@ -22,8 +22,10 @@ import com.google.devtools.ksp.isConstructor import com.google.devtools.ksp.processing.Resolver import com.google.devtools.ksp.processing.SymbolProcessor import com.google.devtools.ksp.processing.SymbolProcessorEnvironment +import com.google.devtools.ksp.symbol.ClassKind import com.google.devtools.ksp.symbol.KSAnnotated import com.google.devtools.ksp.symbol.KSClassDeclaration +import com.squareup.kotlinpoet.ANY import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.ParameterSpec @@ -66,6 +68,32 @@ class TestProcessor(private val env: SymbolProcessorEnvironment) : SymbolProcess .filterNot { it.shortName.getShortName() == "ExampleAnnotation" } .map { it.toAnnotationSpec() }.asIterable(), ) + val allSupertypes = decl.superTypes.toList() + val (superclassReference, superInterfaces) = if (allSupertypes.isNotEmpty()) { + val superClass = allSupertypes.firstOrNull { + val resolved = it.resolve() + resolved is KSClassDeclaration && resolved.classKind == ClassKind.CLASS + } + if (superClass != null) { + superClass to allSupertypes.filterNot { it == superClass } + } else { + null to allSupertypes + } + } else { + null to allSupertypes + } + + superclassReference?.let { + val typeName = it.toTypeName(decl.typeParameters.toTypeParameterResolver()) + if (typeName != ANY) { + superclass(typeName) + } + } + addSuperinterfaces( + superInterfaces.map { it.toTypeName(decl.typeParameters.toTypeParameterResolver()) } + .filterNot { it == ANY } + .toList(), + ) } val classTypeParams = decl.typeParameters.toTypeParameterResolver() classBuilder.addTypeVariables( diff --git a/interop/ksp/test-processor/src/test/kotlin/com/squareup/kotlinpoet/ksp/test/processor/TestProcessorTest.kt b/interop/ksp/test-processor/src/test/kotlin/com/squareup/kotlinpoet/ksp/test/processor/TestProcessorTest.kt index 06518effc9..d17f229d98 100644 --- a/interop/ksp/test-processor/src/test/kotlin/com/squareup/kotlinpoet/ksp/test/processor/TestProcessorTest.kt +++ b/interop/ksp/test-processor/src/test/kotlin/com/squareup/kotlinpoet/ksp/test/processor/TestProcessorTest.kt @@ -483,6 +483,118 @@ class TestProcessorTest { ) } + @Test + fun regression_1513() { + val compilation = prepareCompilation( + kotlin( + "Example.kt", + """ + package test + + import com.squareup.kotlinpoet.ksp.test.processor.ExampleAnnotation + + interface Repository + @ExampleAnnotation + class RealRepository @Inject constructor() : Repository + """, + ), + ) + + val result = compilation.compile() + assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) + val generatedFileText = File(compilation.kspSourcesDir, "kotlin/test/TestRealRepository.kt") + .readText() + + assertThat(generatedFileText).isEqualTo( + """ + package test + + import kotlin.String + + public class RealRepository : Repository + + """.trimIndent(), + ) + } + + @Test + fun regression_1513_annotation() { + val compilation = prepareCompilation( + kotlin( + "Example.kt", + """ + package test + + import com.squareup.kotlinpoet.ksp.test.processor.ExampleAnnotation + + annotation class GenericAnnotation + + @ExampleAnnotation + @GenericAnnotation + class RealRepository + """, + ), + ) + + val result = compilation.compile() + assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) + val generatedFileText = File(compilation.kspSourcesDir, "kotlin/test/TestRealRepository.kt") + .readText() + + assertThat(generatedFileText).isEqualTo( + """ + package test + + import kotlin.String + + @GenericAnnotation + public class RealRepository + + """.trimIndent(), + ) + } + + @Test + fun regression_1304() { + val compilation = prepareCompilation( + kotlin( + "Example.kt", + """ + package test + + import com.squareup.kotlinpoet.ksp.test.processor.ExampleAnnotation + + interface Flow + typealias LeAlias = Map + + @ExampleAnnotation + class RealRepository { + lateinit var prop: LeAlias + lateinit var complicated: Flow + } + """, + ), + ) + + val result = compilation.compile() + assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) + val generatedFileText = File(compilation.kspSourcesDir, "kotlin/test/TestRealRepository.kt") + .readText() + + assertThat(generatedFileText).isEqualTo( + """ + package test + + public class RealRepository { + public lateinit var prop: LeAlias + + public lateinit var complicated: Flow + } + + """.trimIndent(), + ) + } + private fun prepareCompilation(vararg sourceFiles: SourceFile): KotlinCompilation { return KotlinCompilation() .apply {