From b3de2b3548ca8f2d6393746e8ad900a1d394e1d0 Mon Sep 17 00:00:00 2001 From: "christian.hausknecht" Date: Thu, 22 Feb 2024 17:54:34 +0100 Subject: [PATCH] Make lenses genration more resilient with KSP >= 1.9.x Obviously the KSP based LensesAnnotationProcessor was more resilient in the past before we upgraded to Kotlin 1.9.x and appropriate KSP with RC15. We encountered some issues with generating lenses that only came with this bad warning: ``` w: [ksp] Unable to process:dev.fritz2.lens.LensesProcessor: SomeClass ``` This was due to some not resolvable types inside the annotated data class, like calls to functions from other libs or delegated properties. This PR fixes such issues, as we ignore everything from the annotated class but the primary constructor. The latter is the only interesting piece for our lens generation. --- .../kotlin/dev/fritz2/lens/LensesProcessor.kt | 12 ++++++++++-- .../kotlin/dev/fritz2/lens/LensesProcessorTests.kt | 12 ++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lenses-annotation-processor/src/jvmMain/kotlin/dev/fritz2/lens/LensesProcessor.kt b/lenses-annotation-processor/src/jvmMain/kotlin/dev/fritz2/lens/LensesProcessor.kt index e7f4cc095..a54ef70de 100644 --- a/lenses-annotation-processor/src/jvmMain/kotlin/dev/fritz2/lens/LensesProcessor.kt +++ b/lenses-annotation-processor/src/jvmMain/kotlin/dev/fritz2/lens/LensesProcessor.kt @@ -35,10 +35,18 @@ class LensesProcessor( ) : SymbolProcessor { override fun process(resolver: Resolver): List { + val checkOnlyCtor: (KSNode?, KSNode) -> Boolean = { _, node -> + when (node) { + is KSClassDeclaration -> node.primaryConstructor?.validate() ?: false + else -> false + } + } + val lensesAnnotated = resolver.getSymbolsWithAnnotation(Lenses::class.qualifiedName!!) - val unableToProcess = lensesAnnotated.filterNot { it.validate() } - lensesAnnotated.filter { it is KSClassDeclaration && it.validate() } + val unableToProcess = lensesAnnotated.filterNot { it.validate(checkOnlyCtor) } + + lensesAnnotated.filter { it is KSClassDeclaration && it.validate(checkOnlyCtor) } .forEach { it.accept(LensesVisitor(), Unit) } return unableToProcess.toList() diff --git a/lenses-annotation-processor/src/jvmTest/kotlin/dev/fritz2/lens/LensesProcessorTests.kt b/lenses-annotation-processor/src/jvmTest/kotlin/dev/fritz2/lens/LensesProcessorTests.kt index a68706503..cacebfaae 100644 --- a/lenses-annotation-processor/src/jvmTest/kotlin/dev/fritz2/lens/LensesProcessorTests.kt +++ b/lenses-annotation-processor/src/jvmTest/kotlin/dev/fritz2/lens/LensesProcessorTests.kt @@ -308,19 +308,27 @@ class LensesProcessorTests { @ExperimentalPathApi @Test - fun `lenses ignore none ctor or private ctor properties`() { + fun `lenses ignore none ctor or private ctor properties, other annotations, delegated none ctor properties and functions in companion`() { val kotlinSource = SourceFile.kotlin( "dataClassesForLensesTests.kt", """ package dev.fritz2.lenstest import dev.fritz2.core.Lenses + // should not disturb + import kotlinx.serialization.Serializable + import kotlinx.serialization.json.Json @Lenses + @Serializable // should not disturb data class Foo(val bar: Int, private val ignoredProp: Int) { // ^^^^^^^ // private field -> no lens possible! - companion object + companion object { + // should not disturb + fun toJson(foo: Foo) = Json.decodeFromString(serializer(), foo) + } val ignored = bar + 1 // must not appear in lens! + val ignoredDelegated by lazy { bar + 1 } // must not appear in lens! } """ )