Skip to content

Commit

Permalink
[Optics] Show error for generic classes in KSP plug-in (#2636)
Browse files Browse the repository at this point in the history
  • Loading branch information
serras authored Jan 12, 2022
1 parent 8659228 commit a12a883
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 30 deletions.
46 changes: 23 additions & 23 deletions arrow-libs/optics/arrow-optics-ksp-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id(libs.plugins.kotlin.jvm.get().pluginId)
id(libs.plugins.kotlin.multiplatform.get().pluginId)
alias(libs.plugins.arrowGradleConfig.kotlin)
alias(libs.plugins.arrowGradleConfig.publish)
}
Expand All @@ -11,27 +11,27 @@ kotlin {
apply(from = property("TEST_COVERAGE"))
apply(from = property("ANIMALSNIFFER_MPP"))

dependencies {
implementation(libs.ksp)

testImplementation(libs.kotlin.stdlibJDK8)
testImplementation(libs.junitJupiter)
testImplementation(libs.junitJupiterEngine)
testImplementation(libs.assertj)
testImplementation(libs.classgraph)
testImplementation(libs.kotlinCompileTesting) {
exclude(
group = libs.classgraph.get().module.group,
module = libs.classgraph.get().module.name
)
exclude(
group = libs.kotlin.stdlibJDK8.get().module.group,
module = libs.kotlin.stdlibJDK8.get().module.name
)
kotlin {
sourceSets {
jvmMain {
dependencies {
implementation(libs.ksp)
}
}
jvmTest {
dependencies {
implementation(libs.kotlin.stdlibJDK8)
implementation(libs.junitJupiter)
implementation(libs.junitJupiterEngine)
implementation(libs.assertj)
implementation(libs.classgraph)
implementation(libs.kotlinCompileTesting)
implementation(libs.kotlinCompileTestingKsp)
runtimeOnly(projects.arrowOpticsKspPlugin)
runtimeOnly(projects.arrowAnnotations)
runtimeOnly(projects.arrowCore)
runtimeOnly(projects.arrowOptics)
}
}
}
testImplementation(libs.kotlinCompileTestingKsp)
testRuntimeOnly(projects.arrowOpticsKspPlugin)
testRuntimeOnly(projects.arrowAnnotations)
testRuntimeOnly(projects.arrowCore)
testRuntimeOnly(projects.arrowOptics)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import arrow.optics.plugin.internals.join
import arrow.optics.plugin.internals.noCompanion
import arrow.optics.plugin.internals.otherClassTypeErrorMessage
import arrow.optics.plugin.internals.snippets
import arrow.optics.plugin.internals.typeParametersErrorMessage
import com.google.devtools.ksp.processing.CodeGenerator
import com.google.devtools.ksp.processing.Dependencies
import com.google.devtools.ksp.processing.KSPLogger
Expand Down Expand Up @@ -36,14 +37,21 @@ class OpticsProcessor(private val codegen: CodeGenerator, private val logger: KS
return
}

// check that it does not have type arguments
if (klass.typeParameters.isNotEmpty()) {
logger.error(klass.simpleName.asString().typeParametersErrorMessage, klass)
return
}

// check that the companion object exists
val companion = klass.companionObject
if (companion == null) {
if (klass.companionObject == null) {
logger.error(klass.simpleName.asString().noCompanion, klass)
return
}

adt(klass, logger).snippets().groupBy(Snippet::fqName).values.map(List<Snippet>::join).forEach {
val adts = adt(klass, logger)
val snippets = adts.snippets()
snippets.groupBy(Snippet::fqName).values.map(List<Snippet>::join).forEach {
val writer =
codegen
.createNewFile(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@ val String.otherClassTypeErrorMessage
"""
|$this cannot be annotated with @optics
| ^
|
|Only data and sealed classes can be annotated with @optics annotation""".trimMargin()
|Only data and sealed classes can be annotated with @optics""".trimMargin()

val String.typeParametersErrorMessage
get() =
"""
|$this cannot be annotated with @optics
| ^
|Only classes with no type parameters can be annotated with @optics""".trimMargin()

val String.lensErrorMessage
get() =
Expand Down Expand Up @@ -56,10 +62,14 @@ val String.dslErrorMessage
get() =
"""
|Cannot generate DSL (arrow.optics.BoundSetter) for $this
| ^
| ^
|arrow.optics.OpticsTarget.DSL is an invalid @optics argument for $this.
|It is only valid for data classes and sealed classes.
""".trimMargin()

val String.noCompanion
get() = "@optics annotated class $this needs to declare companion object."
get() =
"""
|$this must declare a companion object
| ^
|A companion object is required for the generated optics""".trimMargin()
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package arrow.optics.plugin

import arrow.optics.plugin.internals.typeParametersErrorMessage
import org.junit.jupiter.api.Test

class LensTests {
Expand Down Expand Up @@ -32,4 +33,34 @@ class LensTests {
|val r = i != null
""".evals("r" to true)
}

@Test
fun `Lenses which mentions imported elements`() {
"""
|$imports
|import kotlin.time.Duration
|
|@optics
|data class OpticsTest(val time: Duration) {
| companion object
|}
|
|val i: Lens<OpticsTest, Duration> = OpticsTest.time
|val r = i != null
""".evals("r" to true)
}

@Test
fun `Lenses which mentions type arguments`() {
"""
|$imports
|@optics
|data class OpticsTest<A>(val field: A) {
| companion object
|}
|
|val i: Lens<OpticsTest, Int> = OpticsTest<Int>.time
|val r = i != null
""".failsWith { it.contains("OpticsTest".typeParametersErrorMessage) }
}
}

0 comments on commit a12a883

Please sign in to comment.