diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/OpticsProcessor.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/OpticsProcessor.kt index 63dac0b4695..7b3b72c23c5 100644 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/OpticsProcessor.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/OpticsProcessor.kt @@ -6,6 +6,7 @@ import arrow.optics.plugin.internals.asFileText import arrow.optics.plugin.internals.join import arrow.optics.plugin.internals.noCompanion import arrow.optics.plugin.internals.otherClassTypeErrorMessage +import arrow.optics.plugin.internals.qualifiedNameOrSimpleName import arrow.optics.plugin.internals.snippets import arrow.optics.plugin.internals.typeParametersErrorMessage import com.google.devtools.ksp.processing.CodeGenerator @@ -33,19 +34,19 @@ class OpticsProcessor(private val codegen: CodeGenerator, private val logger: KS private fun processClass(klass: KSClassDeclaration) { // check that it is sealed or data if (!klass.isSealed && !klass.isData) { - logger.error(klass.simpleName.asString().otherClassTypeErrorMessage, klass) + logger.error(klass.qualifiedNameOrSimpleName.otherClassTypeErrorMessage, klass) return } // check that it does not have type arguments if (klass.typeParameters.isNotEmpty()) { - logger.error(klass.simpleName.asString().typeParametersErrorMessage, klass) + logger.error(klass.qualifiedNameOrSimpleName.typeParametersErrorMessage, klass) return } // check that the companion object exists if (klass.companionObject == null) { - logger.error(klass.simpleName.asString().noCompanion, klass) + logger.error(klass.qualifiedNameOrSimpleName.noCompanion, klass) return } diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/domain.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/domain.kt index 89be73d75e9..61235678a14 100644 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/domain.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/domain.kt @@ -4,10 +4,10 @@ import com.google.devtools.ksp.symbol.KSClassDeclaration import com.google.devtools.ksp.symbol.KSName import java.util.Locale -data class ADT(val pckg: KSName, val el: KSClassDeclaration, val targets: List) { - val sourceClassName = el.qualifiedName?.asString() ?: el.simpleName - val sourceName = el.simpleName.asString().replaceFirstChar { it.lowercase(Locale.getDefault()) } - val simpleName = el.simpleName.asString() +data class ADT(val pckg: KSName, val declaration: KSClassDeclaration, val targets: List) { + val sourceClassName = declaration.qualifiedNameOrSimpleName + val sourceName = declaration.simpleName.asString().replaceFirstChar { it.lowercase(Locale.getDefault()) } + val simpleName = declaration.simpleName.asString() val packageName = pckg.asString() operator fun Snippet.plus(snippet: Snippet): Snippet = diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/dsl.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/dsl.kt index 9c412bb07e2..69cf6e992d2 100644 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/dsl.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/dsl.kt @@ -3,21 +3,21 @@ package arrow.optics.plugin.internals fun generateLensDsl(ele: ADT, optic: DataClassDsl): Snippet = Snippet( `package` = ele.packageName, - name = ele.simpleName, + name = ele.sourceClassName, content = processLensSyntax(ele, optic.foci) ) fun generateOptionalDsl(ele: ADT, optic: DataClassDsl): Snippet = Snippet( `package` = ele.packageName, - name = ele.simpleName, + name = ele.sourceClassName, content = processOptionalSyntax(ele, optic) ) fun generatePrismDsl(ele: ADT, isoOptic: SealedClassDsl): Snippet = Snippet( `package` = ele.packageName, - name = ele.simpleName, + name = ele.sourceClassName, content = processPrismSyntax(ele, isoOptic) ) diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/isos.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/isos.kt index 8d03c00fd4a..40ef5656d2b 100644 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/isos.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/isos.kt @@ -1,7 +1,7 @@ package arrow.optics.plugin.internals internal fun generateIsos(ele: ADT, target: IsoTarget) = - Snippet(`package` = ele.packageName, name = ele.simpleName, content = processElement(ele, target)) + Snippet(`package` = ele.packageName, name = ele.sourceClassName, content = processElement(ele, target)) inline val Target.targetNames inline get() = foci.map(Focus::className) diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/lenses.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/lenses.kt index 7b9057ece2e..db1c8a2381c 100644 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/lenses.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/lenses.kt @@ -5,7 +5,7 @@ import java.util.Locale internal fun generateLenses(ele: ADT, target: LensTarget) = Snippet( `package` = ele.packageName, - name = ele.simpleName, + name = ele.sourceClassName, content = processElement(ele, target.foci) ) @@ -20,12 +20,22 @@ private fun String.toUpperCamelCase(): String = } ) -private fun processElement(ele: ADT, foci: List): String = +private fun processElement(adt: ADT, foci: List): String = foci.joinToString(separator = "\n") { focus -> """ - |inline val ${ele.sourceClassName}.Companion.${focus.lensParamName()}: $Lens<${ele.sourceClassName}, ${focus.className}> inline get()= $Lens( - | get = { ${ele.sourceName}: ${ele.sourceClassName} -> ${ele.sourceName}.${focus.paramName.plusIfNotBlank(prefix = "`", postfix = "`")} }, - | set = { ${ele.sourceName}: ${ele.sourceClassName}, value: ${focus.className} -> ${ele.sourceName}.copy(${focus.paramName.plusIfNotBlank(prefix = "`", postfix = "`")} = value) } + |inline val ${adt.sourceClassName}.Companion.${focus.lensParamName()}: $Lens<${adt.sourceClassName}, ${focus.className}> inline get()= $Lens( + | get = { ${adt.sourceName}: ${adt.sourceClassName} -> ${adt.sourceName}.${ + focus.paramName.plusIfNotBlank( + prefix = "`", + postfix = "`" + ) + } }, + | set = { ${adt.sourceName}: ${adt.sourceClassName}, value: ${focus.className} -> ${adt.sourceName}.copy(${ + focus.paramName.plusIfNotBlank( + prefix = "`", + postfix = "`" + ) + } = value) } |) |""".trimMargin() } diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/optional.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/optional.kt index ea9c8b1b8d2..c03dfcd8bab 100644 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/optional.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/optional.kt @@ -12,7 +12,12 @@ internal fun generateOptionals(ele: ADT, target: OptionalTarget) = private fun processElement(ele: ADT, foci: List): String = foci.joinToString(separator = "\n") { focus -> fun getOrModifyF(toNullable: String = "") = - "{ ${ele.sourceName}: ${ele.sourceClassName} -> ${ele.sourceName}.${focus.paramName.plusIfNotBlank(prefix = "`", postfix = "`")}$toNullable?.right() ?: ${ele.sourceName}.left() }" + "{ ${ele.sourceName}: ${ele.sourceClassName} -> ${ele.sourceName}.${ + focus.paramName.plusIfNotBlank( + prefix = "`", + postfix = "`" + ) + }$toNullable?.right() ?: ${ele.sourceName}.left() }" fun setF(fromNullable: String = "") = "${ele.sourceName}.copy(${focus.paramName.plusIfNotBlank(prefix = "`", postfix = "`")} = value$fromNullable)" diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/prism.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/prism.kt index 19bbaae8e88..77fa0b377d1 100644 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/prism.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/prism.kt @@ -3,7 +3,7 @@ package arrow.optics.plugin.internals internal fun generatePrisms(ele: ADT, target: PrismTarget) = Snippet( `package` = ele.packageName, - name = ele.simpleName, + name = ele.sourceClassName, imports = setOf("import arrow.core.left", "import arrow.core.right", "import arrow.core.identity"), content = processElement(ele, target.foci) 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 38e515bd371..27a0929ab4a 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 @@ -4,6 +4,7 @@ import arrow.optics.plugin.isData import arrow.optics.plugin.isSealed import com.google.devtools.ksp.processing.KSPLogger import com.google.devtools.ksp.symbol.KSClassDeclaration +import com.google.devtools.ksp.symbol.KSDeclaration import com.google.devtools.ksp.symbol.KSType import com.google.devtools.ksp.symbol.KSTypeArgument import java.util.Locale @@ -15,10 +16,10 @@ internal fun adt(c: KSClassDeclaration, logger: KSPLogger): ADT = c.targets().map { target -> when (target) { OpticsTarget.LENS -> - evalAnnotatedDataClass(c, c.simpleName.asString().lensErrorMessage, logger) + evalAnnotatedDataClass(c, c.qualifiedNameOrSimpleName.lensErrorMessage, logger) .let(::LensTarget) OpticsTarget.OPTIONAL -> - evalAnnotatedDataClass(c, c.simpleName.asString().optionalErrorMessage, logger) + evalAnnotatedDataClass(c, c.qualifiedNameOrSimpleName.optionalErrorMessage, logger) .let(::OptionalTarget) OpticsTarget.ISO -> evalAnnotatedIsoElement(c, logger).let(::IsoTarget) OpticsTarget.PRISM -> evalAnnotatedPrismElement(c, logger).let(::PrismTarget) @@ -44,11 +45,14 @@ internal fun evalAnnotatedPrismElement( ) } else -> { - logger.error(element.simpleName.asString().prismErrorMessage, element) + logger.error(element.qualifiedNameOrSimpleName.prismErrorMessage, element) emptyList() } } +internal val KSDeclaration.qualifiedNameOrSimpleName: String + get() = (qualifiedName ?: simpleName).asString() + internal fun KSClassDeclaration.sealedSubclassFqNameList(): List = getSealedSubclasses().mapNotNull { it.qualifiedName?.asString() }.toList() @@ -88,11 +92,11 @@ internal fun evalAnnotatedIsoElement(element: KSClassDeclaration, logger: KSPLog .zip(element.getConstructorParamNames(), Focus.Companion::invoke) .takeIf { it.size <= 22 } ?: run { - logger.error(element.simpleName.asString().isoTooBigErrorMessage, element) + logger.error(element.qualifiedNameOrSimpleName.isoTooBigErrorMessage, element) emptyList() } else -> { - logger.error(element.simpleName.asString().isoErrorMessage, element) + logger.error(element.qualifiedNameOrSimpleName.isoErrorMessage, element) emptyList() } } diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/LensTests.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/LensTests.kt index fc44c0b60fd..d913d5006a2 100755 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/LensTests.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/LensTests.kt @@ -38,14 +38,13 @@ class LensTests { fun `Lenses which mentions imported elements`() { """ |$imports - |import kotlin.time.Duration | |@optics - |data class OpticsTest(val time: Duration) { + |data class OpticsTest(val time: kotlin.time.Duration) { | companion object |} | - |val i: Lens = OpticsTest.time + |val i: Lens = OpticsTest.time |val r = i != null """.evals("r" to true) } diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/Utils.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/Utils.kt index 01ba04b72c7..2ca7093e4c7 100644 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/Utils.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/Utils.kt @@ -6,6 +6,7 @@ const val imports = import arrow.optics.* import arrow.optics.dsl.* import arrow.optics.typeclasses.* + import kotlin.time.Duration.Companion.hours """ const val dslModel = @@ -19,7 +20,7 @@ const val dslModel = @optics data class Company(val name: String, val address: Address) { companion object } - @optics data class Employee(val name: String, val company: Company?) { + @optics data class Employee(val name: String, val company: Company?, val weeklyWorkingHours: kotlin.time.Duration = 5.hours) { companion object } @optics data class Employees(val employees: List) {