Skip to content

Commit

Permalink
Fix arguments handling in KSType.toTypeName() (#1529)
Browse files Browse the repository at this point in the history
* Add supertypes and classes to TestProcessor outputs

* Revert odd arguments switch

* Add a few regression tests

* Don't make superclass positional
  • Loading branch information
ZacSweers authored Apr 27, 2023
1 parent 478163e commit c2f0810
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>
@ExampleAnnotation
class RealRepository @Inject constructor() : Repository<String>
""",
),
)

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<String>
""".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<T>
@ExampleAnnotation
@GenericAnnotation<String>
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<String>
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<T>
typealias LeAlias = Map<Int, String>
@ExampleAnnotation
class RealRepository {
lateinit var prop: LeAlias
lateinit var complicated: Flow<LeAlias>
}
""",
),
)

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<LeAlias>
}
""".trimIndent(),
)
}

private fun prepareCompilation(vararg sourceFiles: SourceFile): KotlinCompilation {
return KotlinCompilation()
.apply {
Expand Down

0 comments on commit c2f0810

Please sign in to comment.