diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/processor.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/processor.kt index 61db8b17d65..3efd323d984 100644 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/processor.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/processor.kt @@ -5,6 +5,7 @@ import arrow.optics.plugin.isSealed import arrow.optics.plugin.isValue import com.google.devtools.ksp.processing.KSPLogger import com.google.devtools.ksp.symbol.* +import com.google.devtools.ksp.symbol.Variance.INVARIANT import java.util.Locale internal fun adt(c: KSClassDeclaration, logger: KSPLogger): ADT = @@ -153,12 +154,12 @@ internal fun evalAnnotatedIsoElement( internal fun KSClassDeclaration.getConstructorTypesNames(): List = primaryConstructor?.parameters?.map { it.type.resolve().qualifiedString() }.orEmpty() -internal fun KSType.qualifiedString(): String = when (declaration) { +internal fun KSType.qualifiedString(prefix: String = ""): String = when (declaration) { is KSTypeParameter -> { - val n = declaration.simpleName.asSanitizedString() + val n = declaration.simpleName.asSanitizedString(prefix = prefix) if (isMarkedNullable) "$n?" else n } - else -> when (val qname = declaration.qualifiedName?.asSanitizedString()) { + else -> when (val qname = declaration.qualifiedName?.asSanitizedString(prefix = prefix)) { null -> toString() else -> { val withArgs = when { @@ -172,7 +173,7 @@ internal fun KSType.qualifiedString(): String = when (declaration) { internal fun KSTypeArgument.qualifiedString(): String = when (val ty = type?.resolve()) { null -> toString() - else -> ty.qualifiedString() + else -> ty.qualifiedString(prefix = "${variance.label} ".takeIf { variance != INVARIANT }.orEmpty()) } internal fun KSClassDeclaration.getConstructorParamNames(): List = diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/utils.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/utils.kt index d61dde87043..f7bce0daf7d 100644 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/utils.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/utils.kt @@ -12,8 +12,8 @@ fun String.plusIfNotBlank(prefix: String = "", postfix: String = "") = /** * Sanitizes each delimited section if it matches with Kotlin reserved keywords. */ -fun KSName.asSanitizedString(delimiter: String = ".") = - asString().splitToSequence(delimiter).joinToString(delimiter) { if (it in kotlinKeywords) "`$it`" else it } +fun KSName.asSanitizedString(delimiter: String = ".", prefix: String = "") = + asString().splitToSequence(delimiter).joinToString(delimiter, prefix) { if (it in kotlinKeywords) "`$it`" else it } private val kotlinKeywords = setOf( diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/DSLTests.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/DSLTests.kt index 22a21a55d6d..5a41c95f3f8 100755 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/DSLTests.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/DSLTests.kt @@ -76,5 +76,23 @@ class DSLTests { """.compilationSucceeds() } + @Test + fun `DSL works with variance, issue #3057`() { + """ + |$`package` + |$imports + | + |sealed interface ITest { + | data class Test1(val test: String) : ITest + |} + | + |interface Extendable + |@optics + |data class TestClass(val details: Extendable) { + | companion object + |} + """.compilationSucceeds() + } + // Db.content.at(At.map(), One).set(db, None) }